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)
    
  • 相关阅读:
    洛谷 P1508 Likecloud-吃、吃、吃
    Codevs 1158 尼克的任务
    2017.10.6 国庆清北 D6T2 同余方程组
    2017.10.6 国庆清北 D6T1 排序
    2017.10.3 国庆清北 D3T3 解迷游戏
    2017.10.3 国庆清北 D3T2 公交车
    2017.10.3 国庆清北 D3T1 括号序列
    2017.10.4 国庆清北 D4T1 财富
    2017.10.7 国庆清北 D7T2 第k大区间
    2017.10.7 国庆清北 D7T1 计数
  • 原文地址:https://www.cnblogs.com/jiakecong/p/14716889.html
Copyright © 2011-2022 走看看