經過使用閉包函數(嵌套函數),來達到不改變原方法,而對原方法添加功能的做用閉包
1 import time 2 from functools import wraps 3 4 5 def timer(f): 6 @wraps(f) 7 def inner(*args,**kwargs): 8 start = time.time() 9 res = f(*args,**kwargs) 10 end = time.time() 11 print(end - start) 12 return res 13 return inner 14 15 16 @timer #func = timer(func(a)) 17 def func(a): 18 '''this is a function''' 19 return f'function:{a}' 20 21 res = func('f') 22 print(res) 23 print(func.__name__) 24 print(func.__doc__)
對func函數添加計算時間的功能,16行@語法,稱之爲語法糖,等同於 func = timer(func(a));app
__name__ 和__doc__方法,可查看函數的方法和註釋,因爲使用了裝飾器,故顯示的都爲裝飾器中的屬性,若要顯示原來屬性,則使用functools的wrap方法對裝飾的函數進行裝飾;函數
對裝飾器函數在外包一層函數,使用布爾值進行判斷調用this
1 Flag = True 2 def outer(Flag): 3 def timer(f): 4 @wraps(f) 5 def inner(*args,**kwargs): 6 if Flag: 7 start = time.time() 8 res = f(*args,**kwargs) 9 end = time.time() 10 print(end - start) 11 else: 12 res = f(*args,**kwargs) 13 return res 14 return inner 15 return timer 16 17 @outer(Flag) 18 def func(a): 19 '''this is a function''' 20 return f'function:{a}' 21 22 res = func('hello') 23 print(res)
經過修改布爾值,就可調控該裝飾器是否執行spa
當有多個裝飾器時,離函數最近的裝飾器先執行code
1 def wrapper1(func): 2 def inner(): 3 print('wrapper1 ,before func') 4 func() 5 print('wrapper1 ,after func') 6 return inner 7 8 def wrapper2(func): 9 def inner(): 10 print('wrapper2 ,before func') 11 func() 12 print('wrapper2 ,after func') 13 return inner 14 15 @wrapper2 16 @wrapper1 17 def f(): 18 print('in f') 19 20 f()
實際執行順序爲wrapper1,而後是wrapper2;在調用wrapper1時,返回的爲wrapper1的inner函數,此時對該inner函數,進行wrapper2的裝飾,故輸出以下圖。blog
該輸出如,照鏡子,f爲鏡子,我稱之爲鏡子輸出io