随记,保留函数元信息

2020-06-22  本文已影响0人  大梦三千秋

@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 保留函数元信息的内容。

上一篇 下一篇

猜你喜欢

热点阅读