zoukankan      html  css  js  c++  java
  • python笔记36-装饰器之wraps

    前言

    前面一篇对python装饰器有了初步的了解了,但是还不够完美,领导看了后又提出了新的需求,希望运行的日志能显示出具体运行的哪个函数。

    name__和__doc

    __name__用于获取函数的名称,__doc__用于获取函数的docstring内容(函数的注释)

    import time
    
    def func_a(a):
        '''func_a --> hello'''
        print("hello"+a)
        time.sleep(0.5)
        return True
    
    
    def func_b(b, c="xx"):
        '''func_b --> world'''
        print("world"+b+c)
        time.sleep(0.8)
        return True
    
    if __name__ == '__main__':
        print(func_a.__name__)  # 结果 func_a
        print(func_a.__doc__)   # func_a --> hello
        print(func_b.__name__)  # func_b
        print(func_b.__doc__)   # func_b --> world
    

    装饰器加函数名称日志

    在装饰器里面添加2行代码,打印正在运行函数的名称和docstring内容

    import time
    
    
    def runtime(func):
        '''runtime decorators'''
        def wrapper(*args, **kwargs):
            '''wrapper inner fuction'''
            print("running function : %s" % func.__name__)   
            print("docstring: %s" % func.__doc__)
            start = time.time()
            f = func(*args, **kwargs)     # 原函数
            end = time.time()
            print("运行时长:%.4f 秒" % (end-start))
            return f
        return wrapper
    
    
    @runtime
    def func_a(a):
        '''func_a --> hello'''
        print("hello"+a)
        time.sleep(0.5)
        return True
    
    
    @runtime
    def func_b(b, c="xx"):
        '''func_b --> world'''
        print("world"+b+c)
        time.sleep(0.8)
        return True
    
    if __name__ == '__main__':
        func_a("a")
        print(func_a.__name__)
        print(func_a.__doc__)
    

    运行结果

    running function : func_a
    docstring: func_a --> hello
    helloa
    运行时长:0.5008 秒
    wrapper
    wrapper inner fuction
    

    从运行的结果可以看出,func_a.__name__运行的结果是wrapper, func_a.__doc__运行的结果是wrapper inner fuction。
    也就是说被装饰后的函数其实已经是另外一个函数了(函数名等函数属性会发生改变),那这个问题如何解决呢?
    这就需要用到functools里面的一个wraps函数了

    functools

    当func_a函数被装饰后,导致了一个副作用:自身的函数属性和docstring内容变成了wrapper函数的属性了。
    这里需用到functools里面的一个wraps的装饰器来消除这样的副作用。

    import time
    from functools import wraps
    
    def runtime(func):
        '''runtime decorators'''
        @wraps(func)
        def wrapper(*args, **kwargs):
            '''wrapper inner fuction'''
            print("running function : %s" % func.__name__)
            print("docstring: %s" % func.__doc__)
            start = time.time()
            f = func(*args, **kwargs)     # 原函数
            end = time.time()
            print("运行时长:%.4f 秒" % (end-start))
            return f
        return wrapper
    
    

    只需在wrapper函数上加上@wraps(func)即可解决

    运行结果

    running function : func_a
    docstring: func_a --> hello
    helloa
    运行时长:0.5004 秒
    func_a
    func_a --> hello
    

    类装饰器

    带参数的装饰器,可以写成类装饰器

    import time
    from functools import wraps
    
    class runtime(object):
        '''runtime class decorators'''
        def __init__(self, slowly=1):
            self.slowly = slowly
    
        def __call__(self, func):
            @wraps(func)
            def wrapper(*args, **kwargs):
                '''wrapper inner fuction'''
                print("running function : %s" % func.__name__)
                print("docstring: %s" % func.__doc__)
                start = time.time()
                f = func(*args, **kwargs)     # 原函数
                end = time.time()
                t = end-start
                time.sleep((self.slowly-1)*t)  # 延迟效果
                new_end = time.time()
                print("运行时长:%.4f 秒" % (new_end-start))
                return f
            return wrapper
    
    
    @runtime(1.5)
    def func_a(a):
        '''func_a --> hello'''
        print("hello"+a)
        time.sleep(0.5)
        return True
    
    
    @runtime()
    def func_b(b, c="xx"):
        '''func_b --> world'''
        print("world"+b+c)
        time.sleep(0.8)
        return True
    
    if __name__ == '__main__':
        func_a("a")
        print(func_a.__name__)
        print(func_a.__doc__)
    
    

    运行结果

    running function : func_a
    docstring: func_a --> hello
    helloa
    运行时长:0.7522 秒
    func_a
    func_a --> hello
    

    python自动化交流 QQ群:779429633

  • 相关阅读:
    HearthBuddy投降插件2019-11-01的使用
    正则表达式在线分析 regex online analyzer
    Tips to write better Conditionals in JavaScript
    The fileSyncDll.ps1 is not digitally signed. You cannot run this script on the current system.
    Cannot capture jmeter traffic in fiddler
    JMETER + POST + anti-forgery token
    input type color
    HearthBuddy修改系统时间
    What are all the possible values for HTTP “Content-Type” header?
    UDK性能优化
  • 原文地址:https://www.cnblogs.com/yoyoketang/p/10803575.html
Copyright © 2011-2022 走看看