軟件面世時,不可能把全部的功能都設計好,再將來的一兩年功能會陸續上線,按期更新迭代,軟件以前所用的源代碼,函數裏面的代碼以及函數的調用方式通常不會修改,能夠在源碼不改變的狀況下,增長一些新的功能.python
裝飾器是以功能爲導向的,就是一個函數,在不改變原被裝飾的函數的源代碼以及調用方式下,爲其添加額外的功能.網絡
python中裝飾器 : 完美的詮釋開放封閉原則函數
裝飾器就是一個函數 : 他要裝飾一個函數,在不改變原函數的源碼以及調用方式的前提下,給其增長一個額外的功能優化
import time def index(): time.sleep(2) # 模擬一下網絡延遲以及代碼的效率 print('歡迎訪問博客園主頁') def home(name): time.sleep(3) # 模擬一下網絡延遲以及代碼的效率 print(f'歡迎訪問{name}主頁') def timer(func): # func = index def inner(): start_time = time.time() func() end_time = time.time() print(f'此函數的執行效率爲{end_time-start_time}') return inner index = timer(index) index() # 此爲裝飾器的雛形,雖然知足了開放封閉原則,可是若是當源代碼又返回值時則此代碼不夠完善.
當須要與原代碼返回值一致的時候須要注意一下兩點設計
明確源代碼的返回值應該返回給誰code
實際返回給了誰源碼
如何修改博客
import time def index(): time.sleep(2) # 模擬一下網絡延遲以及代碼的效率 return '歡迎訪問博客園主頁' def timer(func): # func = index def inner(): start_time = time.time() ret = func() end_time = time.time() return ret return inner index = timer(index) # inner print(index()) # print(inner()) # 實際的返回值返給了inner,爲了讓返回值與源代碼一致,須要進行賦值操做,這樣就保證了返回值一致 # 如今代碼已經知足原函數的返回值與裝飾器以後的返回值保持一致了,還缺乏的就是傳參一致.
當須要與原代碼傳參保持一致須要注意一下幾點class
明確源代碼的傳參應該傳參給誰效率
實際傳參給了誰
如何修改
import time def home(name,age): time.sleep(3) # 模擬一下網絡延遲以及代碼的效率 print(name,age) print(f'歡迎訪問{name}主頁') def timer(func): # func = home def inner(*args,**kwargs): # 函數定義時,*表明聚合:因此你的args = ('歲月',18) start_time = time.time() func(*args,**kwargs) # 函數的執行時,*表明打散:因此*args --> *('歲月',18)--> func('歲月',18) end_time = time.time() return inner home = timer(home) home('歲月',18) # 這樣利用*的打散與聚合的原理,將這些實參經過inner函數的中間完美的傳遞到給了相應的形參。
代碼優化 : 語法糖,Python給咱們提供了一個簡化機制,用一個很簡單的符號去代替相似home = timer(home)這一句話。
注意 : 由於涉及函數的調用,@timer必定要放在被裝飾函數的上方,不然會報錯.
def timer(func): # func = home def inner(*args,**kwargs): start_time = time.time() func(*args,**kwargs) end_time = time.time() return inner @timer # 此處代替了home = timer(home) def home(name,age): time.sleep(3) # 模擬一下網絡延遲以及代碼的效率 print(name,age) print(f'歡迎訪問{name}主頁') home('歲月',18)
至此標準版的裝飾器以下,徹底符合代碼開放封閉原則:
def warpter(f): def inner(*args,**kwargs) # 此處執行被裝飾函數以前的操做 ret=f(*args,**kwargs) # 此處執行被裝飾函數以後的操做 return ret return inner