本隨筆是對Python札記 -- 裝飾器的一些補充。
使用裝飾器的時候,被裝飾函數的一些屬性會丟失,比如如下代碼:
1 #!/usr/bin/env python 2 3 def deco(func): 4 def wrapper(): 5 PRint "Wrap start" 6 func() 7 print "Wrap end/n" 8 return wrapper 9 10 @deco11 def foo():12 """Docstring for foo"""13 print "In foo():"14 15 foo()16 print foo.__name__17 print foo.__doc__
輸出如下:
$ python decorator_test.pyWrap startIn foo():Wrap endwrapperNone可以發現,__name__屬性成了wrapper,而__doc__屬性則成了None。這對于平常使用多少帶來些不便,總不能給每個使用裝飾器的函數都重寫__name__和__doc__吧。
Python的functools提供的update_wrapper和wraps可以有效解決這個問題。不過update_wrapper是用方法的形式進行調用,而wraps則是用裝飾器來封裝了update_wrapper。示例代碼分別如下:
1 #!/usr/bin/env python 2 from functools import update_wrapper 3 4 def deco(func): 5 def wrapper(): 6 print "Wrap start" 7 func() 8 print "Wrap end/n" 9 return update_wrapper(wrapper,func) #調用update_wrapper方法10 11 @deco12 def foo():13 """Docstring for foo"""14 print "In foo():"15 16 foo()17 print foo.__name__18 print foo.__doc__
1 #!/usr/bin/env python 2 from functools import wraps 3 4 def deco(func): 5 @wraps(func) #使用裝飾器來實現 6 def wrapper(): 7 print "Wrap start" 8 func() 9 print "Wrap end/n"10 return wrapper11 12 @deco13 def foo():14 """Docstring for foo"""15 print "In foo():"16 17 foo()18 print foo.__name__19 print foo.__doc__
現在被deco裝飾過的foo方法,可以保留之前的__name__和__doc__屬性了。
$ python decorator_test_with_update_wrapper.pyWrap startIn foo():Wrap endfooDocstring for foo$ python decorator_test_with_wraps.pyWrap startIn foo():Wrap endfooDocstring for foo
新聞熱點
疑難解答