Python的 decorator 本質(zhì)上就是一個(gè)高階函數(shù),它接收一個(gè)函數(shù)作為參數(shù),然后,返回一個(gè)新函數(shù)。
使用 decorator 用Python提供的 @ 語法,這樣可以避免手動(dòng)編寫 f = decorate(f) 這樣的代碼。
考察一個(gè)@log的定義:
def log(f): def fn(x): print('call ' + f.__name__ + '()...') return f(x) return fn
對于階乘函數(shù),@log工作得很好:
@log def factorial(n): return reduce(lambda x,y: x*y, range(1, n+1)) print(factorial(10))
結(jié)果:
call factorial()... 3628800
但是,對于參數(shù)不是一個(gè)的函數(shù),調(diào)用將報(bào)錯(cuò):
@log def add(x, y): return x + y print(add(1, 2))
>>> print(add(1, 2)) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: fn() takes 1 positional argument but 2 were given
因?yàn)?add() 函數(shù)需要傳入兩個(gè)參數(shù),但是 @log 寫死了只含一個(gè)參數(shù)的返回函數(shù)。
要讓 @log 自適應(yīng)任何參數(shù)定義的函數(shù),可以利用Python的 args 和 *kwargs,保證任意個(gè)數(shù)的參數(shù)總是能正常調(diào)用:
def log(f): def fn(*args, **kwargs): print('call ' + f.__name__ + '()...') return f(*args, **kwargs) return fn
請編寫一個(gè)@performance,它可以打印出函數(shù)調(diào)用的時(shí)間。
計(jì)算函數(shù)調(diào)用的時(shí)間可以記錄調(diào)用前后的當(dāng)前時(shí)間戳,然后計(jì)算兩個(gè)時(shí)間戳的差。
參考答案:
import time def performance(f): def fn(*args, **kw): t1 = time.time() r = f(*args, **kw) t2 = time.time() print('call %s() in %fs' % (f.__name__, (t2 - t1))) return r return fn @performance def factorial(n): return reduce(lambda x,y: x*y, range(1, n+1)) print(factorial(10))
請驗(yàn)證,完成請求
由于請求次數(shù)過多,請先驗(yàn)證,完成再次請求
打開微信掃碼自動(dòng)綁定
綁定后可得到
使用 Ctrl+D 可將課程添加到書簽
舉報(bào)