max*_*max 9 python decorator python-3.x
decorator模块的功能与functools.wraps密切相关.两者之间有什么区别(从Python 3.3/3.4开始)?
根据与 BrenBarn 的讨论,现在functools.wraps还保留了包装函数的签名。恕我直言,这使得decorator装饰器几乎过时了。
from inspect import signature
from functools import wraps
def dec(func):
def wrapper(*args, **kwargs):
return func(*args, **kwargs)
return wrapper
def dec2(func):
@wraps(func)
def wrapper(*args, **kwargs):
return func(*args, **kwargs)
return wrapper
def foo(a: int, b):
pass
print(signature(dec(foo)))
print(signature(dec2(foo)))
# Prints:
# (*args, **kwargs)
# (a:int, b)
Run Code Online (Sandbox Code Playgroud)
请注意,必须使用signature而不是getargspec。用python 3.4测试。
有两个区别:
decorator真正保留了签名,而functools.wraps没有,即使在 python 3.7 中也是如此。通过签名,我的意思help()是,signature()当然__dict__,而且包装器在用户提供错误参数的情况下会在TypeError 不执行的情况下引发正确的结果。正如这篇文章中所解释的,functools.wraps 似乎保留了签名,但实际上并没有保留它。
decorator当参数kwargs不是 var-positional 时,您总是会收到它们 - 这使得实现您的包装器变得更加容易。因此,functools.wraps根据名称获取参数值要困难得多,因为它可能位于*args、 in**kwargs或任何地方(如果它是可选参数并且不是由用户提供)
由于我functool.wraps非常喜欢 API 但又想解决以上两个问题,所以我创建了makefun. @wraps它提出了使用与 完全相同的技巧的泛化decorator,甚至支持签名修改,例如添加和删除参数。它已经被多个项目使用,请毫不犹豫地尝试一下!