通用装饰器示例
from functools import wraps
def my_decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
# 在函数调用前添加的逻辑
print("Before the function is called.")
# 调用被装饰的函数并获取返回值
result = func(*args, **kwargs)
# 在函数调用后添加的逻辑
print("After the function is called.")
# 返回被装饰函数的返回值
return result
# 返回包装过的函数
return wrapper
这个装饰器可以被用于任何需要在函数执行前后添加逻辑的场景。例如,我们可以通过如下方式使用它来打印函数的执行时间:
import time
@my_decorator
def my_function():
time.sleep(1)
print("Function executed.")
my_function()
输出结果如下:
Before the function is called.
Function executed.
After the function is called.
你也可以通过向 wrapper()
函数中传递参数来为装饰器添加更多的灵活性。
关于 @wraps 的说明
functools.wraps
是一个装饰器,它可以用来简化装饰器的实现,并保留被装饰函数的元数据信息(如函数名、文档字符串、参数列表等)。
在定义装饰器时,我们通常会将被装饰函数作为参数传递给装饰器,然后返回一个新的函数。但是,如果我们不使用 wraps
装饰被返回的新函数,那么它将会丢失被装饰函数的元数据信息,这可能导致一些问题,例如在调试和文档生成时无法正确显示函数的信息。
wraps
装饰器可以解决这个问题。它将被返回的新函数的元数据信息设置为与被装饰函数相同,从而使得它们在编写和阅读代码时更容易识别和理解。具体来说,wraps
装饰器会将被返回的新函数的 __name__
、__doc__
、__module__
和 __annotations__
等属性设置为被装饰函数对应的属性,这样我们就可以直接访问被装饰函数的元数据信息了。
以下是一个使用 wraps
装饰器的示例:
from functools import wraps
def my_decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
# 在函数调用前添加的逻辑
print("Before the function is called.")
# 调用被装饰的函数并获取返回值
result = func(*args, **kwargs)
# 在函数调用后添加的逻辑
print("After the function is called.")
# 返回被装饰函数的返回值
return result
# 返回包装过的函数
return wrapper
@my_decorator
def my_function():
"""这是一个示例函数"""
print("Function executed.")
# 输出函数名和文档字符串
print(my_function.__name__)
print(my_function.__doc__)
输出结果如下:
my_function
这是一个示例函数
可以看到,使用 wraps
装饰器后,被装饰函数的元数据信息得以保留。