• Python札记 -- 装饰器补充


        本随笔是对Python札记 -- 装饰器的一些补充。

        使用装饰器的时候,被装饰函数的一些属性会丢失,比如如下代码:

     1 #!/usr/bin/env python
     2 
     3 def deco(func):
     4     def wrapper():
     5         print "Wrap start"
     6         func()
     7         print "Wrap end
    "
     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__

    输出如下:

    $ 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。示例代码分别如下:

     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
    "
     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
    "
    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__属性了。

    $ 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
  • 相关阅读:
    Java入门3.2---线程池
    Java入门3.1---多线程
    打开ppt报"powerpoint无法加载mathtype加载项"错误
    LATEX排版总结
    casbin 权限系统
    Go netpoll I/O 多路复用构建原生网络模型之源码深度解析
    使用winsw包装服务将nginx包装为Windows服务
    Node.js 的模块系统
    一文读懂 babel7 的配置文件加载逻辑
    vue-cli是什么?和 webpack是什么关系?
  • 原文地址:https://www.cnblogs.com/PandaBamboo/p/4016260.html
Copyright © 2020-2023  润新知