上一篇实现了一个监测函数执行时间的装饰器,但这个装饰器存在缺陷,它只能装饰那些没有参数的函数,下面的用法就是有问题的
import time
def cost(func):
    def warpper():
        t1 = time.time()
        res = func()
        t2 = time.time()
        print(func.__name__ + "执行耗时" +  str(t2-t1))
        return res
    return warpper
@cost
def test(sleep_time):
    time.sleep(sleep_time)
test(1)
程序报错,原因在于test函数有一个sleep_time参数,但是在执行res = func()时,却没有传递这个参数,对装饰器稍作修改,修改后代码如下
def cost(func):
    def warpper(*args, **kwargs):
        t1 = time.time()
        res = func(*args, **kwargs)
        t2 = time.time()
        print(func.__name__ + "执行耗时" +  str(t2-t1))
        return res
    return warpper
在函数warpper中增加可变参数,在调用执行被装饰的函数时传递这些可变参数,这样就不会有问题了,现在,这个装饰器可以装饰任何你想装饰的函数
函数被装饰以后,一些原本属于自己的自省信息会丢失,先来看装饰前的样子
def test(sleep_time):
    """
    测试装饰器
    :param sleep_time:
    :return:
    """
    time.sleep(sleep_time)
print(test.__name__)
print(test.__doc__)
执行输出结果
test
    测试装饰器
    :param sleep_time:
    :return:
程序会输出函数的名称和函数的注释doc信息,但是被装饰以后,这些信息就会丢失
@cost
def test(sleep_time):
    """
    测试装饰器
    :param sleep_time:
    :return:
    """
    time.sleep(sleep_time)
print(test.__name__)
print(test.__doc__)
程序输出结果为
warpper
None
可以看到,实际输出的都是warpper的自省信息,这是我们不希望看到的,为此,我们要使用一项修复技术
import time
from functools import wraps
def cost(func):
    @wraps(func)
    def warpper(*args, **kwargs):
        t1 = time.time()
        res = func(*args, **kwargs)
        t2 = time.time()
        print(func.__name__ + "执行耗时" +  str(t2-t1))
        return res
    return warpper
@cost
def test(sleep_time):
    """
    测试装饰器
    :param sleep_time:
    :return:
    """
    time.sleep(sleep_time)
print(test.__name__)
print(test.__doc__)
functools模块有一个wraps函数,它可以避免函数被装饰后丢失自省信息,增加@wraps(func)即可,这样,程序最后输出的就test自身的信息
 
            扫描关注, 与我技术互动
QQ交流群: 211426309
 
                        分享日常研究的python技术和遇到的问题及解决方案