Python的 decorator 本質上就是一個高階函數,它接收一個函數作為參數,然后,返回一個新函數。
使用 decorator 用Python提供的 @ 語法,這樣可以避免手動編寫 f = decorate(f) 這樣的代碼。
考察一個@log的定義:
def log(f): def fn(x): print('call ' + f.__name__ + '()...') return f(x) return fn
對于階乘函數,@log工作得很好:
@log def factorial(n): return reduce(lambda x,y: x*y, range(1, n+1)) print(factorial(10))
結果:
call factorial()... 3628800
但是,對于參數不是一個的函數,調用將報錯:
@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
因為 add() 函數需要傳入兩個參數,但是 @log 寫死了只含一個參數的返回函數。
要讓 @log 自適應任何參數定義的函數,可以利用Python的 args 和 *kwargs,保證任意個數的參數總是能正常調用:
def log(f): def fn(*args, **kwargs): print('call ' + f.__name__ + '()...') return f(*args, **kwargs) return fn
請編寫一個@performance,它可以打印出函數調用的時間。
計算函數調用的時間可以記錄調用前后的當前時間戳,然后計算兩個時間戳的差。
參考答案:
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))
請驗證,完成請求
由于請求次數過多,請先驗證,完成再次請求
打開微信掃碼自動綁定
綁定后可得到
使用 Ctrl+D 可將課程添加到書簽
舉報