之前寫Flask應(yīng)用的時候就用過,但是無奈那時候水平太低,還沒有研究到這里。最近我就決定把Python的這些高級概念全部研究清楚先。
在代碼運行期間動態(tài)增加功能的方式,稱為裝飾器。一個裝飾器的定義類似于閉包,也有可能是一個返回函數(shù)的高階函數(shù)。比如定義一個裝飾器函數(shù):
def log(func):
#內(nèi)部函數(shù)可以使用func
def wrapper(*args,**kw):
print("call %s()"% func.__name__)
return func(*args,**kw)
return wrapper
#使用語法糖來定義一個有裝飾器的函數(shù)
@log
def now():
print("2014")
#另外被裝飾器裝飾的函數(shù)的__name__會發(fā)生改變
print(now.__name__)
#輸出wrapper,因為相當(dāng)于這樣調(diào)用
#log(now) 返回的是wrapper函數(shù)```
由于上述原因,有些依賴函數(shù)簽名的代碼執(zhí)行就會出錯,所以需要將now的\_\_name\_\_變量賦值給wrapper,使用functools.wraps來實現(xiàn)這一點:
import functools
def log(func):
#相當(dāng)于調(diào)用wraps(func)(wrapper)
#這樣就將wrapper的name變量轉(zhuǎn)變成func.name
@functools.wraps(func)
def wrapper(args,kwargs):
print('call %s():' % func.name)
return func(args,**kwargs)
return wrapper
@log
def now():
print("2014")
輸出now
print(now.name)```
下來編寫一個如果decorator本身需要傳入?yún)?shù)的裝飾器函數(shù),這個函數(shù)就必須是一個返回decorator的高階函數(shù)。
def log(text):
def decorator(func):
def wrapper(*args,**kw):
print("%s %s():"%(text,func.__name__))
return func(*args,**kw)
return wrapper
return decorator
#使用這個decorator
#log('execute')返回時decorator
#所以就相當(dāng)于調(diào)用decorator(now)
#因此在定義decorator的下面那個函數(shù)下寫
#functools.wraps(func)
@log('execute')
def now():
print("2014")```
下面是完整的一個,改變wrapper的\_\_name\_\_變量的函數(shù)定義。
def log1(text):
def decorator(func):
@functools.wraps(func)
def wrapper(args,kwargs):
print("%s %s():"%(text,func.name))
return func(args,**kwargs)
return wrapper
return decorator
@log1('execute')
def now():
print("2014")
print(now.name)
now()```