装饰器副作用
from typing import Any
def get_func_info(func):
def wrap(param: Any) -> None:
"""this is the wrap function"""
func(param)
return wrap
@get_func_info
def func(param: str) -> None:
"""打印“世界你好”"""
print(param)
def main():
print(f'func name is: {func.__name__}')
print(f'func docs is: {func.__doc__}')
print(f'func annotations is: {func.__annotations__}')
func('Hello World')
if __name__ == '__main__':
main()
输出:
func name is: wrap
func docs is: this is the wrap function
func annotations is: {'param': typing.Any, 'return': None}
Hello World
解释:
@get_func_info 装饰器等价于 func = get_func_info(func)
所以 func() 实际指向的是 wrap()
因此输出的 wrap 的名称、文档和注解
这就是装饰器的副作用,装饰器不会改变原有函数的功能,但会改变原有函数的一些属性
解决办法就是使用 functools.wraps 装饰 装饰器的内部函数,代码如下:
from functools import wraps
from typing import Any
def get_func_info(func):
# 注意此处,使用 @wraps(func) 装饰 装饰器的内部函数,抵消装饰器对原函数带来的副作用
@wraps(func)
def wrap(param: Any) -> None:
"""this is the wrap function"""
func(param)
return wrap
@get_func_info
def func(param: str) -> None:
"""打印“世界你好”"""
print(param)
def main():
print(f'func name is: {func.__name__}')
print(f'func docs is: {func.__doc__}')
print(f'func annotations is: {func.__annotations__}')
func('Hello World')
if __name__ == '__main__':
main()
输出:
func name is: func
func docs is: 打印“世界你好”
func annotations is: {'param': <class 'str'>, 'return': None}
Hello World