@wraps 装饰器
我们平时写函数的时候,可能会在原函数的基础上增加额外的处理,比较常见的如:日志,计时等。
这里就是我们之前提及的装饰器的运用。关于装饰器的简单使用,具体可查看下面的文章进行了解:
Python 装饰器
今天,篇幅不提及过多关于装饰器如何使用,主要说明一下,当装饰器作用在函数上,如何保留原函数的元信息。
在这里,需要用到 functools
库中 @wraps
装饰器来对底层包装函数进行注解。先编写一个计时的装饰器,示例代码如下:
# 计时装饰器
import time
from functools import wraps
def timeit(func):
@wraps(func)
def wrapper(*args, **kwargs):
start = time.time()
res = func(*args, **kwargs)
end = time.time()
print(func.__name__, end - start)
return res
return wrapper
现在使用上面的装饰器来装饰一个简单的计算函数,并检查函数的元信息:
In [11]: @timeit
...: def count(n:int):
...: """simple cacl
...: """
...: while n > 0:
...: n -= 1
...: print("complete!")
...:
In [12]: count(1000000)
complete!
count 0.04680013656616211
In [17]: count.__annotations__
Out[17]: {'n': int}
In [18]: count.__name__
Out[18]: 'count'
In [19]: count.__doc__
Out[19]: 'simple cacl\n '
在这里,可以看到,当我们使用 @wraps
后,被装饰函数的元信息能够保留下。对比下,若是没有使用 @wraps
结果会怎样:
In [22]: count.__annotations__
Out[22]: {}
In [23]: count.__name__
Out[23]: 'wrapper'
In [24]: count.__doc__
此时,被装饰的函数的元信息则全部丢失了。如果希望保留被装饰函数的元信息,那么建议使用 @wraps
复制元信息。
使用 @wraps
还能够通过 __wrapped__
去直接访问被装饰的函数:
In [27]: count.__wrapped__(1000000)
complete!
这里直接访问被装饰函数,只打印出被装饰函数的输入语句 complete!
,并没有输出计时的结果。
以上就是关于 @wraps
保留函数元信息的内容。
网友评论