装饰器:
用一个函数去装饰另一个函数或类,为其提供额外的能力
实现了一种名为代理模式的经典设计模式
横切关注功能(cross-concern):跟正常的业务没有必然联系的功能
这样的功能最适合用装饰器(代理模式)来实现
举个例子:现有模仿下载与上传并记录这个过程耗时功能的函数:
下载:
def download(filename):
start_time = time.time()
print(f'开始下载{filename}')
time.sleep(random.randrange(3, 7))
print(f'{filename}下载完成')
end_time = time.time()
print(f'下载耗时:{(end_time - start_time):.4f}')
上传:
def upload(filename):
start_time = time.time()
print(f'开始上传{filename}')
time.sleep(random.randrange(5,9))
print(f'{filename}上传完成')
end_time = time.time()
print(f'下载耗时:{(end_time - start_time):.4f}')
上述代码显而易见的问题就是代码重复,这是相当糟糕的。这种函数内的重复代码就可以用装饰器来解决。而且当我们不需要记录执行时间时可随时取消。
def log_time(func): # 参数是被装饰的函数
@wraps(func) # 装饰器建议都添加,可随时取消装饰器
def wrapper(*args,**kwargs): #针对原函数带参
# 新功能
result = func(*args,**kwargs) # 调用原函数
# 新功能
return result #返回原函数的返回值
return wrapper # 返回带有装饰功能的函数
装饰器函数的参数是被装饰的函数,它返回的是带有装饰功能的函数
只需要在上述格式空白处添加新功能即可。
本例记录时间功能可编写为:
def log_time(func): # 参数是被装饰的函数
@wraps(func) # 装饰器建议都添加,可随时取消装饰器
def wrapper(*args,**kwargs):
# 新功能
start_time = time.time()
result = func(*args,**kwargs) # 调用原函数
# 新功能
end_time = time.time()
print(f'{func.__name__}执行耗时:{end_time-start_time:.4f}')
return result #返回原函数的返回值
return wrapper # 返回带有装饰功能的函数
写好装饰器有两种使用方法:
def download(filename):
print(f'开始下载{filename}')
time.sleep(random.randrange(3,7))
print(f'{filename}下载完成')
if __name__ == '__main__':
# 装饰器用法一:
download = log_time(download)
download('Python入门.pdf')
#输出:
#开始下载Python入门.pdf
#Python入门.pdf下载完成
#download执行耗时:4.0001
# 装饰器用法二
@log_time
def upload(filename):
print(f'开始上传{filename}')
time.sleep(random.randrange(5,9))
print(f'{filename}上传完成')
#输出:
#开始上传Python人工智能.pdf
#Python人工智能.pdf上传完成
#upload执行耗时:5.0006
上面提到的@wraps具体功能就是取消装饰器的作用,这里就是取消耗时记录:
download.__wrapped__('数据分析.pdf')
#输出:
#开始下载数据分析.pdf
#数据分析.pdf下载完成
版权说明 : 本文为转载文章, 版权归原作者所有 版权申明
原文链接 : https://blog.csdn.net/Lemon_Review/article/details/120188214
内容来源于网络,如有侵权,请联系作者删除!