1. 程式人生 > >python中裝飾器使用

python中裝飾器使用

裝飾器是對已有的模組進行裝飾(新增新功能)的函式。

現有一段程式碼:

1 import time
2 def func1():
3     time.sleep(3)
4     print("in the func1")
5 def func2():
6     time.sleep(2)
7     print("in the func2")
8 func1()
9 func2()

現在需要增加func1和func2的功能,計算段程式碼的執行時間。

思路1:修改函式內的程式碼:

 1 import time
 2 def func1():
 3     start_time = time.time()
4 time.sleep(3) 5 print("in the func1") 6 stop_time = time.time() 7 print("this program run %ss"%(stop_time-start_time)) 8 def func2(): 9 start_time = time.time() 10 time.sleep(2) 11 print("in the func2") 12 stop_time = time.time() 13 print("this program run %ss"%(stop_time-start_time))
14 func1() 15 func2()

每個函式都添加了紅色的程式碼段,如果需要改的func較多時,該方法明顯不適用。並且違反了為函式新增附加功能時的原則1:不能修改被裝飾函式的原始碼。

思路2:增加新函式:

 1 import time
 2 def func1():
 3     time.sleep(3)
 4     print("in the func1")
 5 def func2():
 6     time.sleep(2)
 7     print("in the func2")
 8 def func_new1():
 9     start_time = time.time()
10 func1() 11 stop_time =time.time() 12 print("this program run %ss"%(stop_time-start_time)) 13 def func_new2(): 14 start_time = time.time() 15 func2() 16 stop_time =time.time() 17 print("this program run %ss"%(stop_time-start_time)) 18 func_new1() 19 func_new2()

 

該方法增加了新函式,將原有函式引用至新函式中。但問題又來了,需要改主程式中對原有函式的引用方法,違反了並且違反了為函式新增附加功能時的原則2:不能修改被裝飾函式的呼叫方式。

 

此刻,我們需要新的知識儲備來完善對裝飾器的理解

1.函式的巢狀

2.高階函式

3.函式——變數的關係

高階函式+巢狀函式===》裝飾器

插入名詞的解釋!!

高階函式:滿足下列原則之一的就是高階函式:

  a.把一個函式名當作實參傳給另一個函式的函式。

 1 import time
 2 def bar():
 3     time.sleep(3)
 4     print("in the bar")
 5 def test(func):
 6     start_time = time.time()
 7     func()
 8     stop_time = time.time()
 9     print("the func run time is %s"%(stop_time-start_time))
10 test(bar)

在此函式中,bar作為實參被傳遞給形參func,test(bar)。通過test()函式為bar()增加了新功能,且沒有改變bar()的原始碼。但改變了原有bar()的呼叫方式。

實現了不修改被裝飾函式的原始碼情況下為其新增新功能的目的。

  b.返回值中包含函式名

 1 import time
 2 def bar():
 3     time.sleep(3)
 4     print("in the bar")
 5 def test(func):
 6     print(func)
 7     print()
 8     return func
 9 bar = test(bar)
10 bar()

在此程式碼中,原有函式bar(),然後bar作為函式名被傳給新增函式test(),隨後又作為該函式的返回值。相當與給bar()增加了新的功能(顯示bar()的記憶體地址),但沒有改變bar()的呼叫方式。

巢狀函式:在函式體內宣告的函式(必須是宣告,不能是呼叫)

def test1():
    print("in the test1")
    def test2():
        print("in the test2")
    test2()
test1()

test2()是在test1()中宣告的函式

將高階函式與巢狀函式結合,

 1 import time
 2 def timmer(func):
 3     def deco():
 4         start_time = time.time()
 5         func()
 6         stop_time = time.time()
 7         print("the func run time is %ss"%(stop_time-start_time))
 8     return deco
 9 @timmer    #等於在func1被呼叫前加上func1=timmer(func1)
10 def func1():
11     time.sleep(3)
12     print("in the func1")
13 @timmer
14 def func2():
15     time.sleep(2)
16     print("in the func2")
17 func1()
18 func2()

其中@timmer = func1= timmer(func1),就是在被裝飾的函式前加上裝飾器的名稱。在沒有改變被裝飾程式碼的原始碼及呼叫方式的情況下增加了其功能。