第一次見到functools.wraps是在 Flask Web開發 中,一直不明白怎麼回事。app
裝飾器(decorator)是幹嗎的?對於受到封裝的原函數來講,裝飾器可以在那個函數執行前或者執行後分別運行一些代碼,使得能夠再裝飾器裏面訪問並修改原函數的參數以及返回值,以實現約束定義、調試程序、註冊函數等目標。裝飾器通常返回一個包裝器(wrapper),而functools.wraps就是裝飾包裝器的裝飾器。函數
先來看一個不使用functools.wraps的裝飾器例子。spa
1 def tracer(func): 2 def wrapper(*args, **kwargs): 3 result = func(*args, **kwargs) 4 print('%s(%r,%r)->%r'%(func.__name__,args,kwargs,result)) 5 return result 6 return wrapper 7 8 @tracer 9 def fibonacci(n): 10 if n in (0,1): 11 return n 12 return (fibonacci(n-1)+fibonacci(n-2)) 13 14 15 fibonacci(3) 16 print(fibonacci) 17 print('help:') 18 help(fibonacci)
輸出結果:調試
能夠看到,裝飾器徹底能夠正常工做。。。code
可是,函數的名字變成裝飾器中的包裝器了!!!help內置函數也失效了blog
也就是說,原函數的屬性失效了ci
若是想要保留原函數的屬性,就能夠用到functools.wraps了開發
1 from functools import wraps 2 def tracer(func): 3 @wraps(func) 4 def wrapper(*args, **kwargs): 5 result = func(*args, **kwargs) 6 print('%s(%r,%r)->%r'%(func.__name__,args,kwargs,result)) 7 return result 8 return wrapper 9 10 @tracer 11 def fibonacci(n): 12 if n in (0,1): 13 return n 14 return (fibonacci(n-1)+fibonacci(n-2)) 15 16 17 fibonacci(3) 18 print(fibonacci) 19 print('help:') 20 help(fibonacci)
輸出結果:class
參考資料:Effective Python,第6章 內置模塊import