装饰器是Python中用一个函数装饰另外一个函数或类并为其提供额外功能的语法现象。装饰器本身是一个函数,它的参数是被装饰的函数或类,它的返回值是一个带有装饰功能的函数。很显然,装饰器是一个高阶函数,它的参数和返回值都是函数。
import time
# 定义装饰器函数,它的参数是被装饰的函数或类
def record_time(func):
# 定义一个带装饰功能(记录被装饰函数的执行时间)的函数
# 因为不知道被装饰的函数有怎样的参数所以使用*args和**kwargs接收所有参数
# 在Python中函数可以嵌套的定义(函数中可以再定义函数)
def wrapper(*args, **kwargs):
# 在执行被装饰的函数之前记录开始时间
start = time.time()
# 执行被装饰的函数并获取返回值
result = func(*args, **kwargs)
# 在执行被装饰的函数之后记录结束时间
end = time.time()
# 计算和显示被装饰函数的执行时间
print(f‘{func.__name__}执行时间: {end - start:.3f}秒‘)
# 返回被装饰函数的返回值(装饰器通常不会改变被装饰函数的执行结果)
return result
# 返回带装饰功能的wrapper函数
return wrapper
func = record_time(func)
@装饰器函数
@record_time
def download(filename):
print(f‘开始下载{filename}.‘)
time.sleep(random.randint(2, 6))
print(f‘{filename}下载完成.‘)
如果希望取消装饰器的作用,那么在定义装饰器函数的时候,需要做一些额外的工作。Python标准库functools模块的wraps函数也是一个装饰器,我们将它放在wrapper函数上,这个装饰器可以帮我们保留被装饰之前的函数,这样在需要取消装饰器时,可以通过被装饰函数的
__wrapped__
属性获得被装饰之前的函数。
添加@wraps(func)
于def wrapper
之上:
def record_time(func):
@wraps(func)
def wrapper(*args, **kwargs):
start = time.time()
result = func(*args, **kwargs)
end = time.time()
print(f‘{func.__name__}执行时间: {end - start:.3f}秒‘)
return result
return wrapper
# 取消装饰器 直接调用原函数
download.__wrapped__(‘MySQL必知必会.pdf‘)
# 取消装饰器 调用原函数来覆盖现有函数
upload = upload.__wrapped__
upload(‘Python从新手到大师.pdf‘)
原文:https://www.cnblogs.com/linzhenyu/p/13205481.html