考察上一節(jié)的 @log 裝飾器:
def log(f): def fn(x): print('call ' + f.__name__ + '()...') return f(x) return fn
發(fā)現(xiàn)對于被裝飾的函數(shù),log打印的語句是不能變的(除了函數(shù)名)。
如果有的函數(shù)非常重要,希望打印出'[INFO] call xxx()...'。
有的函數(shù)不太重要,希望打印出'[DEBUG] call xxx()...'。
這時,log函數(shù)本身就需要傳入'INFO'或'DEBUG'這樣的參數(shù),類似這樣:
@log('DEBUG') def my_func(): pass
把上面的定義翻譯成高階函數(shù)的調(diào)用,就是:
my_func = log('DEBUG')(my_func)
上面的語句看上去還是比較繞,再展開一下:
log_decorator = log('DEBUG') my_func = log_decorator(my_func)
上面的語句又相當于:
log_decorator = log('DEBUG') @log_decorator def my_func(): pass
所以,帶參數(shù)的log函數(shù)首先返回一個decorator函數(shù),再讓這個decorator函數(shù)接收my_func并返回新函數(shù),相當于是在原有的二層嵌套里面,增加了一層嵌套:
def log(prefix): def log_decorator(f): def wrapper(*args, **kw): print('[{}] {}()...'.format(prefix, f.__name__)) return f(*args, **kw) return wrapper return log_decorator @log('DEBUG') def test(): pass test()
執(zhí)行結(jié)果:
[DEBUG] test()...
對于這種三層嵌套的decorator定義,你可以先把它拆開:
# 標準decorator: def log_decorator(f): def wrapper(*args, **kw): print('[{}] {}()...'.format(prefix, f.__name__)) return f(*args, **kw) return wrapper return log_decorator # 返回decorator: def log(prefix): return log_decorator(f)
上一節(jié)的@performance只能打印秒,請給 @performace 增加一個參數(shù),允許傳入's'或'ms':
@performance('ms') def factorial(n): return reduce(lambda x,y: x*y, range(1, n+1))
要實現(xiàn)帶參數(shù)的@performance,就需要實現(xiàn):
?my_func = performance('ms')(my_func)
需要三層嵌套的decorator來實現(xiàn)。
參考答案:
import time def performance(unit): def perf_decorator(f): def wrapper(*args, **kwargs): t1 = time.time() r = f(*args, **kwargs) t2 = time.time() t = (t2 - t1) * 1000 if unit == 'ms' else (t2 - t1) print('call {}() in {} {}'.format(f.__name__, t, unit)) return r return wrapper return perf_decorator @performance('ms') def factorial(n): return reduce(lambda x,y: x*y, range(1, n+1)) factorial(10)
請驗證,完成請求
由于請求次數(shù)過多,請先驗證,完成再次請求
打開微信掃碼自動綁定
綁定后可得到
使用 Ctrl+D 可將課程添加到書簽
舉報