Python進階(八)-編寫帶引數decorator
分享一下我的偶像大神的人工智慧教程!http://blog.csdn.net/jiangjunshow
也歡迎轉載我的文章,轉載請註明出處 https://blog.csdn.net/mm2zzyzzp
Python進階(八)-編寫帶引數decorator
繼續考察@log 裝飾器:
def log(f):
def fn(x):
print 'call ' + f.__name__ + '()...'
return f(x)
return fn
- 1
- 2
- 3
- 4
- 5
發現對於被裝飾的函式,log列印的語句是不能變的(除了函式名)。
如果有的函式非常重要,希望打印出’[INFO] call xxx()…’,有的函式不太重要,希望打印出’[DEBUG] call xxx()…’,這時,log函式本身就需要傳入’INFO’或’DEBUG’這樣的引數,類似這樣:
@log('DEBUG')
def my_func():
pass
- 1
- 2
- 3
把上面的定義翻譯成高階函式的呼叫,就是:
my_func = log('DEBUG')(my_func)
- 1
上面的語句看上去還是比較繞,再展開一下:
log_decorator = log('DEBUG')
my_func = log_decorator(my_func)
- 1
- 2
上面的語句又相當於:
log_decorator = log('DEBUG')
@log_decorator
def my_func():
pass
- 1
- 2
- 3
- 4
所以,帶引數的log函式首先返回一個decorator函式,再讓這個decorator函式接收my_func並返回新函式:
def log(prefix):
def log_decorator(f) :
def wrapper(*args, **kw):
print '[%s] %s()...' % (prefix, f.__name__)
return f(*args, **kw)
return wrapper
return log_decorator
@log('DEBUG')
def test():
pass
print test()
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
執行結果:
[DEBUG] test()…
None
對於這種3層巢狀的decorator定義,你可以先把它拆開:
# 標準decorator:
def log_decorator(f):
def wrapper(*args, **kw):
print '[%s] %s()...' % (prefix, f.__name__)
return f(*args, **kw)
return wrapper
return log_decorator
# 返回decorator:
def log(prefix):
return log_decorator(f)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
拆開以後會發現,呼叫會失敗,因為在3層巢狀的decorator定義中,最內層的wrapper引用了最外層的引數prefix,所以,把一個閉包拆成普通的函式呼叫會比較困難。不支援閉包的程式語言要實現同樣的功能就需要更多的程式碼。
舉例
在@performance實現列印秒的同時,請給 @performace 增加一個引數,允許傳入’s’或’ms’:
@performance('ms')
def factorial(n):
return reduce(lambda x,y: x*y, range(1, n+1))
- 1
- 2
- 3
要實現帶引數的@performance,就需要實現:
my_func = performance('ms')(my_func)
- 1
需要3層巢狀的decorator來實現。
參考程式碼:
import time
def performance(unit):
def perf_decorator(f):
def wrapper(*args, **kw):
t1 = time.time()
r = f(*args, **kw)
t2 = time.time()
t = (t2 - t1) * 1000 if unit=='ms' else (t2 - t1)
print 'call %s() in %f %s' % (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))
print factorial(10)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
分享一下我的偶像大神的人工智慧教程!http://blog.csdn.net/jiangjunshow
也歡迎轉載我的文章,轉載請註明出處 https://blog.csdn.net/mm2zzyzzp