Function decorator 有兩個特性:
- 它可以用來替代 decorated 函數
- Decorator 在讀取模組時便執行
以下為一個例子:
def deco(func): print("Init") def wrapper(): print("Before") func() print("After") return wrapper @deco def hello(): print("Hello!") print("Ya!") hello() # Results: # Init # Ya! # Before # Hello! # After
從以上的例子可看出我們把 hello 函數當成參數丟給 deco 函數,也就是類似 deco(hello) 的意思。而 deco 函數在模組的讀取階段就已經執行了,因此會先印出 Init,之後才印出剩下的文字。
例子:函數計時器
這裡用一個函數計時器的例子來展示 function decorator 的用途:
import time def clock(func): def clocked(*args): t0 = time.perf_counter() result = func(*args) elapsed = time.perf_counter() - t0 print('%0.8fs' % elapsed) # 0.10066449s return result return clocked @clock def snooze(seconds): time.sleep(seconds) snooze(0.1)
Standard library 中的 decorator 例子
首先是 functools.lru_cache,它可以用來記錄之前得到的結果。以下為一個例子:import functools @functools.lru_cache() def fib(n): if n < 2: return n return fib(n-2) * fib(n-1) t0 = time.perf_counter() fib(30) elapsed = time.perf_counter() - t0 print('%0.8fs' % elapsed) # With lru_cache: 0.00010853s # Without lru_cache: 0.32648241s
另一個例子是 functools.singledispatch,它可以用來做 generic programming。細節請參考資料 [1]。
沒有留言:
張貼留言