python3 基礎和進階詳細個人筆記整理
lambda表示式
lambda用來宣告匿名函式,用於臨時需要一個類似函式功能的場景,可以結合python的內建函式使用,比如map()。
>>> function=lambda a,b,c: a*b*c # 起名lambda表示式為function
>>> print(function(2,3,4))
24
# 定義一個字典,裡面有兩個鍵f1,f2,對應兩個lambda函式
>>> dict={'f1':(lambda x,y:x+y),'f2':(lambda x,y:x*y)}
>>> print(dict['f1' ](2,3))
5
>>> print(dict['f2'](2,3))
6
關於lambda區域性變數的錯誤:
>>> r=[]
>>> for x in range(10):
... r.append(lambda: x**2)
...
>>> r[1]()
81
>>> r[0]()
81
>>> r[2]()
81
>>> r[3]()
81
>>> x=2
>>> r[1]()
4
>>> r[2 ]()
4
>>> r[3]()
4
如果改為以下則正確:
>>> r=[]
>>> for x in range(10):
... r.append(lambda n=x: n**2)
...
>>> r[0]()
0
>>> r[1]()
1
>>> r[2]()
4
>>> r[3]()
9
>>> x=2
>>> r[0]()
0
>>> r[1]()
1
>>> r[3]()
9
關於以上全域性和區域性錯誤的另一個示例:
>>> f=lambda:i #返回i
>>> i=2
>>> f()
2
>>> i=5
>>> f()
5
>>> i=4
>>> f()
4
生成器
包含yield語句的函式叫做生成器函式。
生成器具有惰性求值的特點,可以用於大資料。
return一旦執行就立刻結束函式;yield則是返回一個值,然後掛起yield語句後面的程式碼,使用__next__()
可以恢復執行。
# 使用生成器生成斐波那契數列
>>> def f():
... a,b=1,1
... while True:
... yield a
... a,b=b,a+b #序列解包
...
>>> a=f()
>>> for i in range(10):
... print(a.__next__(),end=' ')
...
1 1 2 3 5 8 13 21 34 55
簡單的分析(此處是草稿可跳過,我只是看看
markdown的圖表怎麼弄 -_-||)
a | b | yield |
---|---|---|
1 | 1 | 1 |
1 | 2 | 1 |
2 | 3 | 2 |
3 | 5 | 3 |
5 | 8 | 5 |
*args 和 **kwargs
這是魔法變數,實際上args和kwargs不是固定的,可以是任何命名,只要有和*就行。
*args 和 **kwargs 主要用於在函式定義的時候把不定數量的引數傳遞給一個函式。
*args
簡單的例子:
def test_var_args(f_arg, *argv):
print("first normal arg:", f_arg)
for arg in argv:
print("another arg through *argv:", arg)
test_var_args('yasoob', 'python', 'eggs', 'test')
這會產生如下輸出:
first normal arg: yasoob
another arg through *argv: python
another arg through *argv: eggs
another arg through *argv: test
**kwargs
**kwargs 將不定長度的鍵值對,作為引數傳遞給一個函式。
1 def greet_me(*args, **kwargs):
2 for v in args:
3 print("hello, {0}".format(v))
4 for key, value in kwargs.items():
5 print("{0} is {1}".format(key, value))
6
7
8 greet_me('andy', 'smith', name1="jane", name2='john', name3='claire')
輸出:
hello, andy
hello, smith
name1 is jane
name2 is john
name3 is claire
使用 *args 和 **kwargs 來呼叫函式
def test_args_kwargs(arg1, arg2, arg3):
print("arg1:", arg1)
print("arg2:", arg2)
print("arg3:", arg3)
# 使用 *args
args = ("two", 3, 5)
test_args_kwargs(*args)
# 結果:
arg1: two
arg2: 3
arg3: 5
# 使用 **kwargs:
kwargs = {"arg3": 3, "arg2": "two", "arg1": 5}
test_args_kwargs(**kwargs)
# 結果:
arg1: 5
arg2: two
arg3: 3
使用時的順序
標準的引數, 然後是*, 然後是**
some_func(fargs, *args, **kwargs)
修飾器(裝飾器)
是函式巢狀的一個重要應用。
本質:修飾器是一個函式,只不過函式的引數是其它函式,也就是說接受其它函式作為傳入引數,對傳入的函式做一定的修改之後,返回一個新的函式。
從函式中返回函式
1 def hi(name="vic"):
2 def greet():
3 return "now you are in the greet() function. hello vic."
4
5 def welcome():
6 n = name
7 return "now you are in the welcome() function. hello " + n
8
9 if name == "vic":
10 return greet
11 else:
12 return welcome
13
14 a = hi()
15 print(a)
16 #outputs: <function greet at 0x7f2143c01500>
17
18 #上面清晰地展示了`a`現在指向到hi()函式中的greet()函式
19 #現在試試這個
20
21 print(a())
22 #outputs: now you are in the greet() function. hello, vic.
23
24 b = hi('lara')()
25 print(b)
26
27 # namely
28 # b = hi('lara')
29 # print(b())
30
31 #outputs: now you are in the welcome() function. hello lara
什麼是裝飾器
裝飾器裡面定義一個wrap函式對需要裝飾的函式進行包裝,裝飾器返回wrap函式,注意是wrapTheFunction不帶括號
1 def a_new_decorator(a_func):
2
3 def wrapTheFunction():
4 print("I am doing some boring work before executing a_func()")
5
6 a_func()
7
8 print("I am doing some boring work after executing a_func()")
9
10 return wrapTheFunction
11
12 def a_function_requiring_decoration():
13 print("I am the function which needs some decoration to remove my foul smell")
14
15 a_function_requiring_decoration()
16 #outputs: "I am the function which needs some decoration to remove my foul smell"
17
18 # 對a_function_requiring_decoration進行裝飾
19 a_function_requiring_decoration = a_new_decorator(a_function_requiring_decoration)
20 #now a_function_requiring_decoration is wrapped by wrapTheFunction()
21
22 a_function_requiring_decoration()
23 #outputs:I am doing some boring work before executing a_func()
24 # I am the function which needs some decoration to remove my foul smell
25 # I am doing some boring work after executing a_func()
使用@符號修改上面的栗子:
1 def a_new_decorator(a_func):
2
3 def wrapTheFunction():
4 print("I am doing some boring work before executing a_func()")
5
6 a_func()
7
8 print("I am doing some boring work after executing a_func()")
9
10 return wrapTheFunction
11
12 @a_new_decorator # 相當於一種簡寫,在需要裝飾的函式定義上面加上@裝飾器即可。
13 def a_function_requiring_decoration():
14 print("I am the function which needs some decoration to remove my foul smell")
15
16 a_function_requiring_decoration()
17 #outputs:I am doing some boring work before executing a_func()
18 # I am the function which needs some decoration to remove my foul smell
19 # I am doing some boring work after executing a_func()
但是目前存在一個問題:
如果我們執行打印出a_function_requiring_decoration的函式名,會發現實際上答應出了wrapTheFunction
# print the name of the decorated funciton
print(a_function_requiring_decoration.__name__)
會打印出:
wrapTheFunction
而不是我們所想要的“a_function_requiring_decoration”。因為wrapTheFunction重寫了我們函式的名字和註釋文件(docstring)。
可以通過一個內建函式解決這個問題:
functools.wraps
1 #匯入一個內建函式wrap
2 from functools import wraps
3
4 def a_new_decorator(a_func):
5
6 #使用wrap裝飾傳入進來作為的引數函式
7 @wraps(a_func)
8 def wrapTheFunction():
9 print("I am doing some boring work before executing a_func()")
10
11 a_func()
12
13 print("I am doing some boring work after executing a_func()")
14
15 return wrapTheFunction
16
17 @a_new_decorator
18 def a_function_requiring_decoration():
19 print("I am the function which needs some decoration to remove my foul smell")
20
21 a_function_requiring_decoration()
22 #outputs:I am doing some boring work before executing a_func()
23 # I am the function which needs some decoration to remove my foul smell
24 # I am doing some boring work after executing a_func()
25
26 # print the name of the decorated funciton
27 print(a_function_requiring_decoration.__name__)
輸出為:
I am doing some boring work before executing a_func()
I am the function which needs some decoration to remove my foul smell
I am doing some boring work after executing a_func()
a_function_requiring_decoration
另外一個裝飾器使用的示例:
定義函式呼叫之前和之後要執行的程式碼
1 def before(func):
2 def wrapper(*args, **kwargs):
3 print('Before function is called.')
4 return func(*args, **kwargs)
5 return wrapper
6
7 def after(func):
8 def wrapper(*args, **kwargs):
9 result = func(*args, **kwargs)
10 print('After function is called.')
11 return result
12 return wrapper
13
14 @before
15 @after
16 def test():
17 print(3)
執行結果:
Before function is called.
3
After function is called.
協程
協程(Coroutine)可以實現單執行緒併發程式碼。
即各個子任務協作執行的意思,可以解決非同步問題。
這裡寫程式碼片