时间:2021-05-22
问题
你写了一个装饰器作用在某个函数上,但是这个函数的重要的元信息比如名字、文档字符串、注解和参数签名都丢失了。
解决方案
任何时候你定义装饰器的时候,都应该使用 functools 库中的 @wraps 装饰器来注解底层包装函数。例如:
import timefrom functools import wrapsdef timethis(func): ''' Decorator that reports the execution time. ''' @wraps(func) def wrapper(*args, **kwargs): start = time.time() result = func(*args, **kwargs) end = time.time() print(func.__name__, end-start) return result return wrapper下面我们使用这个被包装后的函数并检查它的元信息:
>>> @timethis... def countdown(n):... '''... Counts down... '''... while n > 0:... n -= 1...>>> countdown(100000)countdown 0.008917808532714844>>> countdown.__name__'countdown'>>> countdown.__doc__'\n\tCounts down\n\t'>>> countdown.__annotations__{'n': <class 'int'>}>>>讨论
在编写装饰器的时候复制元信息是一个非常重要的部分。如果你忘记了使用 @wraps , 那么你会发现被装饰函数丢失了所有有用的信息。比如如果忽略 @wraps 后的效果是下面这样的:
>>> countdown.__name__'wrapper'>>> countdown.__doc__>>> countdown.__annotations__{}>>>@wraps 有一个重要特征是它能让你通过属性 __wrapped__ 直接访问被包装函数。例如:
>>> countdown.__wrapped__(100000)>>>__wrapped__ 属性还能让被装饰函数正确暴露底层的参数签名信息。例如:
>>> from inspect import signature>>> print(signature(countdown))(n:int)>>>一个很普遍的问题是怎样让装饰器去直接复制原始函数的参数签名信息, 如果想自己手动实现的话需要做大量的工作,最好就简单的使用 @wraps 装饰器。 通过底层的 __wrapped__ 属性访问到函数签名信息。
以上就是Python如何创建装饰器时保留函数元信息的详细内容,更多关于Python保留函数元信息的资料请关注其它相关文章!
声明:本页内容来源网络,仅供用户参考;我单位不保证亦不表示资料全面及准确无误,也不保证亦不表示这些资料为最新信息,如因任何原因,本网内容或者用户因倚赖本网内容造成任何损失或损害,我单位将不会负任何法律责任。如涉及版权问题,请提交至online#300.cn邮箱联系删除。
本文实例为大家分享了python为被装饰的函数保留元数据的具体代码,供大家参考,具体内容如下案例:在函数对象中保存着一些函数的元数据,如:f.__name__函
Python装饰器,分两部分,一是装饰器本身的定义,一是被装饰器对象的定义。一、函数式装饰器:装饰器本身是一个函数。1.装饰函数:被装饰对象是一个函数[1]装饰
本文实例讲述了Python装饰器原理与用法。分享给大家供大家参考,具体如下:1、装饰器的本质是函数,主要用来装饰其他函数,也就是为其他函数添加附加功能2、装饰器
Python装饰器(decorator)在实现的时候,被装饰后的函数其实已经是另外一个函数了(函数名等函数属性会发生改变),为了不影响,Python的funct
最近学到了一个有趣的装饰器写法,就记录一下。装饰器是一个返回函数的函数。写一个装饰器,除了最常见的在函数中定义函数以外,Python还允许使用类来定义一个装饰器