python-------裝飾器


一、簡單的裝飾器

1.為什么要使用裝飾器呢?

  裝飾器的功能:在不修改原函數及其調用方式的情況下對原函數功能進行擴展

  裝飾器的本質:就是一個閉包函數

那么我們先來看一個簡單的裝飾器:實現計算每個函數的執行時間的功能

 1 import time 
 2 def  wrapper(func):
 3         def inner():
 4               start=time.time()
 5               func()
 6               end=time.time()
 7               print(end-start)
 8         return inner 
 9     
10 def  hahaha():
11         time.sleep(1)
12         print('aaaaa')
13 hahaha=wrapper(hahaha)
14 hahaha()    
簡單的裝飾器

上面的功能有點不簡介,不完美,下面就引進了語法糖。

 1 import time
 2 def wrapper(func):
 3         def inner():
 4                start=time.time()
 5                func()
 6                end=time.time()
 7                print(end-start)
 8         return inner
 9 @wrapper
10 def  kkk():#相當於kkk=wrapper(kkk)
11     print('aaaaa')
12 kkk()             
裝飾器-------語法糖

以上的裝飾器都是不帶參數的函數,現在裝飾一個帶參數的該怎么辦呢?

原函數帶一個參數的裝飾器
 1 import time
 2 def timer(func):
 3     def inner(*args,**kwargs):
 4         start = time.time()
 5         re = func(*args,**kwargs)
 6         end=time.time()
 7         print(end- start)
 8         return re
 9     return inner
10 
11 @timer   #==> func1 = timer(func1)
12 def func1(a,b):
13     print('in func1')
14     print(a,b)
15 
16 @timer   #==> func1 = timer(func1)
17 def func2(a):
18     print('in func2 and get a:%s'%(a))
19     return 'fun2 over'
20 
21 func1(1,2)
22 print(func2('aaaaaa'))
原函數帶多個參數的裝飾器
 1 import time
 2 def timer(func):
 3     def inner(*args,**kwargs):
 4         start = time.time()
 5         re = func(*args,**kwargs)
 6         end=time.time()
 7         print(end - start)
 8         return re
 9     return inner
10 
11 @timer   #==> func1 = timer(func1)
12 def jjj(a):
13     print('in jjj and get a:%s'%(a))
14     return 'fun2 over'
15 
16 jjj('aaaaaa')
17 print(jjj('aaaaaa'))
帶返回值的裝飾器

二、開放封閉原則

1.對擴展是開放的

2.對修改是封閉的

 三、裝飾器的固定結構

 1 import time
 2 def wrapper(func):  # 裝飾器
 3     def inner(*args, **kwargs):
 4         '''函數執行之前的內容擴展'''
 5         ret = func(*args, **kwargs)
 6          '''函數執行之前的內容擴展'''
 7         return ret
 8     return inner
 9 
10 @wrapper  # =====>aaa=timmer(aaa)
11 def aaa():
12     time.sleep(1)
13     print('fdfgdg')
14 aaa()
View Code

 四、帶參數的裝飾器

帶參數的裝飾器:就是給裝飾器傳參

        用處:就是當加了很多裝飾器的時候,現在忽然又不想加裝飾器了,想把裝飾器給去掉了,但是那么多的代碼,一個一個的去閑的麻煩,那么,我們可以利用帶參數的裝飾器去裝飾它,這就他就像一個開關一樣,要的時候就調用了,不用的時候就去掉了。給裝飾器里面傳個參數,那么那個語法糖也要帶個括號。在語法糖的括號內傳參。在這里,我們可以用三層嵌套,弄一個標識為去標識。如下面的代碼示例

 1 # 帶參數的裝飾器:(相當於開關)為了給裝飾器傳參
 2 # F=True#為True時就把裝飾器給加上了
 3 F=False#為False時就把裝飾器給去掉了
 4 def outer(flag):
 5     def wrapper(func):
 6         def inner(*args,**kwargs):
 7             if flag:
 8                 print('before')
 9                 ret=func(*args,**kwargs)
10                 print('after')
11             else:
12                 ret = func(*args, **kwargs)
13             return ret
14         return inner
15     return wrapper
16 
17 @outer(F)#@wrapper
18 def hahaha():
19     print('hahaha')
20 
21 @outer(F)
22 def shuangwaiwai():
23     print('shuangwaiwai')
24 
25 hahaha()
26 shuangwaiwai()
給裝飾器加參數

 五、多個裝飾器裝飾一個函數

 

 1 def qqqxing(fun):
 2     def inner(*args,**kwargs):
 3         print('in qqxing: before')
 4         ret = fun(*args,**kwargs)
 5         print('in qqxing: after')
 6         return ret
 7     return inner
 8 
 9 def pipixia(fun):
10     def inner(*args,**kwargs):
11         print('in qqxing: before')
12         ret = fun(*args,**kwargs)
13         print('in qqxing: after')
14         return ret
15     return inner
16 @qqqxing
17 @pipixia
18 def dapangxie():
19     print('餓了嗎')
20 dapangxie()
21 
22 '''
23 @qqqxing和@pipixia的執行順序:先執行qqqxing里面的 print('in qqxing: before'),然后跳到了pipixia里面的
24         print('in qqxing: before')
25         ret = fun(*args,**kwargs)
26         print('in qqxing: after'),完了又回到了qqqxing里面的 print('in qqxing: after')。所以就如下面的運行結果截圖一樣
27 '''
多個裝飾器裝飾一個函數

 

 

 上例代碼的運行結果截圖

六、統計多少個函數被裝飾了的小應用

 1  統計多少個函數被我裝飾了
 2 l=[]
 3 def wrapper(fun):
 4     l.append(fun)#統計當前程序中有多少個函數被裝飾了
 5     def inner(*args,**kwargs):
 6         # l.append(fun)#統計本次程序執行有多少個帶裝飾器的函數被調用了
 7         ret = fun(*args,**kwargs)
 8         return ret
 9     return inner
10 
11 @wrapper
12 def f1():
13     print('in f1')
14 
15 @wrapper
16 def f2():
17     print('in f2')
18 
19 @wrapper
20 def f3():
21     print('in f3')
22 print(l)
統計多少個函數被裝飾了

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM