基础篇详见:https://blog.youkuaiyun.com/matlab2007/article/details/102896249
(1)带有参数的装饰器
现在函数f中计算a和b的和,然后通过装饰器来统计运行时间,初学者的代码可能如下:
#带有参数的装饰器
def run_time(f):
def wrapper():
start_time = time.time()
f(a,b)
end_time = time.time()
print('程序运行时间为:%s' %(end_time-start_time))
return wrapper
@run_time
def f(a,b):
print('开始计算:')
time.sleep(1)
print('计算结果%d' %(a+b))
f(5,6)
程序运行提示:
TypeError: wrapper() takes 0 positional arguments but 2 were given
正确代码:
def run_time(f):
def wrapper(a,b):
start_time = time.time()
f(a,b)
end_time = time.time()
print('程序运行时间为:%s' %(end_time-start_time))
return wrapper
@run_time
def f(a,b):
print('开始计算:')
time.sleep(1)
print('计算结果%d' %(a+b))
f(5,6)
即内函数wrappe形参如果需要指定的话,则形参的个数必须和被装饰函数f(a,b)的参数个数一致。
(2)无固定参数的装饰器
被装饰的函数其形参个数可能各异,而装饰器将来可能装饰多个函数,所以考虑到装饰器的通用性,装饰器函数的形参往往定义为可变参数。
def run_time(f):
def wrapper(*args,**kwargs):
start_time = time.time()
f(*args,**kwargs)
end_time = time.time()
print('程序运行时间为:%s' %(end_time-start_time))
return wrapper
@run_time
def f(a,b):
print('开始计算:')
time.sleep(1)
print('计算结果%d' %(a+b))
@run_time
def f2(a,b,c):
print('开始计算:')
time.sleep(1)
print('计算结果%d' %(a+b+c))
f2(5,6,7)
f(5,6)
(3)使用多个装饰器,装饰一个函数
def run_time(f):
def wrapper(*args,**kwargs):
start_time = time.time()
f(*args,**kwargs)
end_time = time.time()
print('第一个装饰器')
print('程序运行时间为:%s' %(end_time-start_time))
return wrapper
def run_hello(f):
def wrapper(*args,**kwargs):
f(*args,**kwargs)
print('第二个装饰器,只打印一句话')
return wrapper
@run_hello
@run_time
def f(a,b):
print('开始计算:')
time.sleep(1)
print('计算结果%d' %(a+b))
f(5,6)
运行结果:
开始计算:
计算结果11
第一个装饰器
程序运行时间为:0.9999358654022217
第二个装饰器,只打印一句话
(4)有函数返回值的装饰器
#带有参数的装饰器
def run_time(f):
def wrapper(*args,**kwargs):
start_time = time.time()
w = f(*args,**kwargs)
end_time = time.time()
print('程序运行时间为:%s' %(end_time-start_time))
return w
return wrapper
@run_time
def f(a,b):
return a+b
f(5,6)
如果被装饰的函数有返回值,则wrapper函数内可以用临时变量接受该返回值,打印或作为wrapper函数的返回值均可。