Python札記 -- 裝飾器補充

    本隨筆是對Python札記 -- 裝飾器的一些補充。html

    使用裝飾器的時候,被裝飾函數的一些屬性會丟失,好比以下代碼: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 @deco
11 def foo():
12     """Docstring for foo"""
13     print "In foo():"
14 
15 foo()
16 print foo.__name__
17 print foo.__doc__

輸出以下:app

$ python decorator_test.py
Wrap start
In foo():
Wrap end

wrapper
None

能夠發現,__name__屬性成了wrapper,而__doc__屬性則成了None。這對於日常使用多少帶來些不便,總不能給每一個使用裝飾器的函數都重寫__name__和__doc__吧。函數

    Python的functools提供的update_wrapper和wraps能夠有效解決這個問題。不過update_wrapper是用方法的形式進行調用,而wraps則是用裝飾器來封裝了update_wrapper。示例代碼分別以下:post

 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 @deco
12 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 wrapper
11 
12 @deco
13 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__屬性了。url

$ python decorator_test_with_update_wrapper.py
Wrap start
In foo():
Wrap end

foo
Docstring for foo

$ python decorator_test_with_wraps.py
Wrap start
In foo():
Wrap end

foo
Docstring for foo
相關文章
相關標籤/搜索