上一篇实现了一个监测函数执行时间的装饰器,但这个装饰器存在缺陷,它只能装饰那些没有参数的函数,下面的用法就是有问题的
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