zoukankan      html  css  js  c++  java
  • python进阶(18)@wraps装饰器

    前言

    我们都知道装饰器的作用是在不改变原有的代码基础上,添加新的功能,但是这样会有一个弊端,被装饰的函数某些属性会变改变,接下来我们来看下
     

    案例

    import time
    
    
    def run_time(func):
        def wrapper(*args, **kwargs):
            """时间装饰器"""
            time1 = time.time()
            func(*args, **kwargs)
            time2 = time.time()
            cost_time = time2 - time1
            return f"函数花了{cost_time}秒"
        return wrapper
    
    
    @run_time
    def test():
        """测试"""
        print([i for i in range(1, 100001) if i % 200 == 0])
    
    
    if __name__ == '__main__':
        print(test.__name__)   
        print(test.__doc__)  
    """
    结果
    # wrapper
    # 时间装饰器
    """
    

    可以看到,我们明明打印的是test函数的__name__属性,最后显示的却是run_time的属性。
     
    我们知道@run_time装饰器实际上就等于test = run_time(test),此时我们打印test.__name__实际上test已经指向了wrapper,这样会造成我们打印的时候会打印装饰器的内嵌函数的名字和注释。
     

    使用wraps装饰器解决

    wraps可以将原函数对象的指定属性复制给包装函数对象, 默认有 __module____name____doc____qualname____annotations__或者通过参数选择

    import time
    from functools import wraps
    
    
    def run_time(func):
        @wraps(func)
        def wrapper(*args, **kwargs):
            """时间装饰器"""
            time1 = time.time()
            func(*args, **kwargs)
            time2 = time.time()
            cost_time = time2 - time1
            return f"函数花了{cost_time}秒"
        return wrapper
    
    
    @run_time
    def test():
        """测试"""
        print([i for i in range(1, 100001) if i % 200 == 0])
    
    
    if __name__ == '__main__':
        print(test.__name__)   
        print(test.__doc__) 
    """
    结果:
    test
    测试
    """
    

    我们就只在原来的wrapper内函数上加了一个@wraps(func)装饰器,就可以打印出我们想要的结果了,这是因为wraps可以将原函数对象的指定属性复制给包装函数对象,我们可以查看它的源码

    def wraps(wrapped,
              assigned = WRAPPER_ASSIGNMENTS,
              updated = WRAPPER_UPDATES):
        """Decorator factory to apply update_wrapper() to a wrapper function
    
           Returns a decorator that invokes update_wrapper() with the decorated
           function as the wrapper argument and the arguments to wraps() as the
           remaining arguments. Default arguments are as for update_wrapper().
           This is a convenience function to simplify applying partial() to
           update_wrapper().
        """
        return partial(update_wrapper, wrapped=wrapped,
                       assigned=assigned, updated=updated)
    
  • 相关阅读:
    Cactus详细讲解
    jexus处理静态文件(处理后缀)
    简单的html兼容(参考js和css的常规写法)
    IOHelper(自制常用的输入输出的帮助类)
    @Html.AntiForgeryToken() 源码分析,表单防伪码的生成
    缓存处理类(MemoryCache结合文件缓存)
    MVC过滤大法(过滤静态文件)
    C#文件监控工具(对追加内容的监控并输出)
    C#在Linux上的开发指南
    对java面试文章的技术漫谈的C#技术理解
  • 原文地址:https://www.cnblogs.com/jiakecong/p/14716889.html
Copyright © 2011-2022 走看看