咱們在上一篇文章(Python實例來認識併發與並行)中用到了 @timer
,在函數定義時,加上一個小小的 @timer
,這樣,函數執行結束後,就會自動在控制檯彙報本身運行的時間。html
好比下面這樣:python
@timer def piper(): for i in range(10000): i = i * i ** 10 piper() 輸出: timer: using 0.00600 s
實際上,這個計時器邏輯 @timer
是咱們本身用 Python 中的修飾器特性來實現的。編程
其實咱們不用修飾器,本身也能實現計時的邏輯。併發
def piper(): for i in range(10000): i = i * i ** 10 t = time.time() # 記錄函數開始時時間 piper() print(f"timer: using {time.time() - t :.5f} s") # 獲取函數運行時間並打印
注意到咱們執行函數時,在其上下都包裹上了邏輯。若是咱們但願函數自帶計時邏輯,那麼爲了包住原函數,只能去新定義一個函數。app
def time_wrapper(func): # func 是一個函數 t = time.time() func() print(f"timer: using {time.time() - t :.5f} s") time_wrapper(piper) 輸出: timer: using 0.00600 s
咱們想測試某一個函數運行時間時,將函數名輸入到 time_wrapper
裏面就好。函數
上述代碼顯然有缺點:測試
time_wrapper
是不行的,由於其並無改變 piper
自己因而咱們請出今天的主角 修飾器@wraps 。code
還用咱們的 timer
舉例子,咱們讓全部在 @timer
下的函數,都通過以下處理:htm
def timer(func): @wraps(func) def inner_func(): t = time.time() rts = func() print(f"timer: using {time.time() - t :.5f} s") return rts return inner_func
以 piper
爲例,咱們經歷了以下變化。ip
@timer def 原始piper(): for i in range(10000): i = i * i ** 10
實際上,當你再調用 piper
時,你的 piper
內部邏輯早已變爲:
def 當前piper(): t = time.time() rts = 原始piper() print(f"timer: using {time.time() - t :.5f} s") return rts
本文簡單與讀者朋友們「科普」一下修飾器,注意到咱們這裏實際上僅僅修飾了無參數的函數。其實,修飾器還有許多更加優雅用途,好比傳入參數 *args, **kwargs
,修飾類 __call__
等用法。期待之後我遇到好的應用場景,將經驗分享給朋友們。
記得點個『在看』!
我是小拍,關注我!