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]。
沒有留言:
張貼留言