-
開放封閉原則:
- 開放:對原始碼的拓展是開放的,
- 封閉:對原始碼的修改是封閉的,
-
裝飾器:完全遵循開放封閉原則,即在不改變原函式的代碼以及呼叫方式的前提下,為其增加新的功能,(裝飾器的本質是閉包)
- 舉例:計算func1函式的運行效率,
def func1(): for i in range(10000): i+=1此問題相當于為函式func1增加一個方法,可以計算函式的運行時間,用簡單的time模塊就可以完成,如下:
import time time.perf_counter() func1() print(f'程式運行的時間為:{time.perf_counter()}')但這樣做不滿足開放封閉原則,可更改為如下:
import time def timer(f): def inner(): time.perf_counter() f() print(f'程式運行的時間為:{time.perf_counter()}') return inner func1=timer(func1) func1() #這樣在不改變原函式的呼叫方式下為原函式增加了新的功能,即為原始的裝飾器模型,在運行大型平臺時非常有用, #裝飾器的本質是閉包 import time def timer(f): f=func1 #f為自由變數,指向函式func1的記憶體地址, def inner(): time.perf_counter() f() print(f'程式運行的時間為:{time.perf_counter()}') return inner func1=timer(func1) func1()但如果想要測驗另一個函式(例如func3)的效率,則仍然需要增加一句語法:
func3=timer(func3),假設要測驗的函式過多的話,就會比較麻煩, -
原始裝飾器模型的升級版本:python做了一個優化,提出了一個‘語法糖’的概念,即在撰寫了裝飾器后,需要將裝飾器代碼放在所有代碼的前方,
import time #裝飾器函式 def timer(f): def inner(): time.perf_counter() f() print(f'程式運行的時間為:{time.perf_counter()}') return inner #當要對裝飾器函式呼叫時,在要裝飾函式的前方使用@+裝飾器函式名,如下: @timer #相當于func1=timer(func1) def func1(): for i in range(10000): i+=1 func1() #此時即使有func3,也可以直接在函式前呼叫裝飾器: @timer #會將兩行并為一行讀取:func3=timer(func3) def func3(): pass -
當函式有回傳值時(被裝飾函式有回傳值時):
import time #裝飾器函式 def timer(f): def inner(): time.perf_counter() f() print(f'程式運行的時間為:{time.perf_counter()}') return inner @timer def func1(): for i in range(10000): i+=1 return i print(func1()) #None,無法列印出函式func1的回傳值,此時要對裝飾器進行改進:
import time #裝飾器函式 def timer(f): def inner(): time.perf_counter() r = f() #將回傳值賦值給r print(f'程式運行的時間為:{time.perf_counter()}') return r #將回傳值給inner函式, return inner @timer def func1(): for i in range(10000): i+=1 return i print(func1()) #10000加上裝飾器不應該改變原函式的回傳值,所有func1的回傳值i應該回傳給inner函式,
-
當函式有引數時(被裝飾函式帶引數):
import time #裝飾器函式 def timer(f): def inner(*arg,**kargs): #*的聚合 time.perf_counter() r = f(*arg,**kargs) #*的打散 ,并將回傳值傳給inner函式, print(f'程式運行的時間為:{time.perf_counter()}') return r #將回傳值給inner函式, return inner @timer def func1(num1,num2): for i in range(num1,num2): i+=1 return i print(func1()) # -
標準版的裝飾器:
def wrapper(f): def inner(*arg,**kargs): '''添加額外的功能:執行被裝飾函式之前的操作''' ret = f(*arg,**kargs) '''添加額外的功能:執行被裝飾函式之前的操作''' return ret return inner #裝飾器的呼叫 @wrapper def func(): pass -
裝飾器的應用:
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/162488.html
標籤:Python
