一、簡單的裝飾器
為什麼要使用裝飾器呢? 裝飾器的功能:在不修改原函式及其呼叫方式的情況下對原函式功能進行擴充套件 裝飾器的本質:就是一個閉包函式那麼我們先來看一個簡單的裝飾器:實現計算每個函式的執行時間的功能
import timedef wrapper(func): def inner(): start = time.time() func() end = time.time() print(end - start) return innerdef hahaha(): time.sleep(1) print('aaaaa')hahaha = wrapper(hahaha)hahaha()複製程式碼
上面的功能有點不簡介,不完美,下面就引進了語法糖。
import timedef wrapper(func): def inner(): start = time.time() func() end = time.time() print(end - start) return inner@wrapperdef kkk(): ## 相當於kkk=wrapper(kkk) print('aaaaa')kkk()複製程式碼
以上的裝飾器都是不帶引數的函式,現在裝飾一個帶引數的該怎麼辦呢原函式帶多個引數的裝飾器
import timedef timer(func): def inner(*args,**kwargs): start = time.time() re = func(*args,**kwargs) end=time.time() print(end- start) return re return inner@timer #**>
func1 = timer(func1)def func1(a,b): print('in func1') print(a,b)@timer #**>
func1 = timer(func1)def func2(a): print('in func2 and get a:%s'%(a)) return 'fun2 over'func1(1,2)print(func2('aaaaaa'))複製程式碼
帶返回值的裝飾器
import timedef timer(func): def inner(*args,**kwargs): start = time.time() re = func(*args,**kwargs) end=time.time() print(end - start) return re return inner@timer #**>
func1 = timer(func1)def jjj(a): print('in jjj and get a:%s'%(a)) return 'fun2 over'jjj('aaaaaa')print(jjj('aaaaaa'))複製程式碼
二、開放封閉原則
1.對擴充套件是開放的2.對修改是封閉的
三、裝飾器的固定結構
import timedef wrapper(func): ## 裝飾器 def inner(*args, **kwargs): '''函式執行之前的內容擴充套件''' ret = func(*args, **kwargs) '''函式執行之前的內容擴充套件''' return ret return inner@wrapper ## ****=>
aaa=timmer(aaa)def aaa(): time.sleep(1) print('fdfgdg')aaa()複製程式碼
四、帶引數的裝飾器
帶引數的裝飾器:就是給裝飾器傳參用處: 就是當加了很多裝飾器的時候,現在忽然又不想加裝飾器了,想把裝飾器給去掉了,但是那麼多的程式碼,一個一個的去閒的麻煩,那麼,我們可以利用帶引數的裝飾器去裝飾它,這就他就像一個開關一樣,要的時候就呼叫了,不用的時候就去掉了。給裝飾器裡面傳個引數,那麼那個語法糖也要帶個括號。在語法糖的括號內傳參。在這裡,我們可以用三層巢狀,弄一個標識為去標識。如下面的程式碼示例
## 帶引數的裝飾器:(相當於開關)為了給裝飾器傳參## F=True#為True時就把裝飾器給加上了F=False#為False時就把裝飾器給去掉了def outer(flag): def wrapper(func): def inner(*args,**kwargs): if flag: print('before') ret=func(*args,**kwargs) print('after') else: ret = func(*args, **kwargs) return ret return inner return wrapper@outer(F)#@wrapperdef hahaha(): print('hahaha')@outer(F)def shuangwaiwai(): print('shuangwaiwai')hahaha()shuangwaiwai()給裝飾器加引數複製程式碼
五、多個裝飾器裝飾一個函式
def qqqxing(fun): def inner(*args,**kwargs): print('in qqxing: before') ret = fun(*args,**kwargs) print('in qqxing: after') return ret return innerdef pipixia(fun): def inner(*args,**kwargs): print('in qqxing: before') ret = fun(*args,**kwargs) print('in qqxing: after') return ret return inner@qqqxing@pipixiadef dapangxie(): print('餓了嗎')dapangxie()'''@qqqxing和@pipixia的執行順序:先執行qqqxing裡面的 print('in qqxing: before'),然後跳到了pipixia裡面的 print('in qqxing: before') ret = fun(*args,**kwargs) print('in qqxing: after'),完了又回到了qqqxing裡面的 print('in qqxing: after')。所以就如下面的執行結果截圖一樣'''多個裝飾器裝飾一個函式複製程式碼
六、統計多少個函式被裝飾了的小應用
l=[]def wrapper(fun): l.append(fun)#統計當前程式中有多少個函式被裝飾了 def inner(*args,**kwargs): ## l.append(fun)#統計本次程式執行有多少個帶裝飾器的函式被呼叫了 ret = fun(*args,**kwargs) return ret return inner@wrapperdef f1(): print('in f1')@wrapperdef f2(): print('in f2')@wrapperdef f3(): print('in f3')print(l)複製程式碼