decorator
module和functools.wraps
的功能密切相关。两者之间有什么区别(从Python 3.3 / 3.4开始)?
我发现一个区别:3+ years ago,decorator
支持帮助,而wraps
没有(另请参阅this)。
答案 0 :(得分:4)
主要差异之一列在您链接到的文档中:decorator
保留了包装函数的签名,而wraps
则没有。
答案 1 :(得分:3)
根据与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)
请注意,必须使用signature
而不是getargspec
。用python 3.4测试。
答案 2 :(得分:0)
有两个区别:
decorator
真正保留签名,而functools.wraps
则不保留签名,即使在python 3.7中也是如此。签名,当然是指help()
和signature()
以及所有__dict__
,但是包装程序会提出正确的TypeError
而根本不执行如果用户提供了错误的参数。如this post中所述,functools.wraps
出现是为了保留签名,但并没有真正保留它。
decorator
的总是在kwargs
中收到参数时,它们不是可变位置的-这使实现包装器变得容易得多。使用functools.wraps
时,根据其名称获取参数值要困难得多,因为它可能位于*args
,**kwargs
或其他任何地方(如果它是可选参数且未由用户提供)
由于我非常喜欢functool.wraps
API,但是想解决上述两个问题,因此我创建了makefun
。它提出了@wraps
的概括,它使用与decorator
完全相同的技巧,甚至支持签名修改,例如添加和删除参数。它已经被多个项目使用,请尝试一下!