decorator
模块和functools.wraps
的功能密切相关。那么这两者的区别是什么(基于Python 3.3 / 3.4)?我知道其中一个区别:在三年前,
decorator
支持帮助文档,而wraps
不支持(参见这里),请注意也有这个链接。decorator
模块和functools.wraps
的功能密切相关。那么这两者的区别是什么(基于Python 3.3 / 3.4)?decorator
支持帮助文档,而wraps
不支持(参见这里),请注意也有这个链接。和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 上进行了测试。getargspec
或者更新且推荐的 getfullargspec
单独使用时无法正常工作,但是当与 inspect.unwrap
结合使用时可以正常工作:https://docs.python.org/3/library/inspect.html#inspect.unwrap - Pekka Klärck其中一个主要的区别在你提供的文档中已经列出:decorator
保留了被包装函数的签名,而 wraps
则没有。
functools.wraps
现在保留签名吗?我在文档中没有看到任何相关内容,但是我没有安装Python 3.5来测试它。 - BrenBarninspect.getargspec
返回原始函数的“真实”参数,而不是通用的*args
/**kwargs
签名。 - BrenBarngetargspec
现在已经被弃用了,而signature
运行正常。 - BrenBarnfunctools.wraps
保留了函数签名,但只是表面上的,因为help
和signature
遵循__wrapped__
属性;在误用的情况下,它不会引发正确的错误。请参见下面的答案:https://dev59.com/uGYr5IYBdhLWcg3wKHEp#55363013 - smariemakefun
。它提出了一种对 `@wraps` 进行了推广的方法,使用与 `decorator` 完全相同的技巧,甚至支持修改签名,例如添加和删除参数。它已经被多个项目使用,请不要犹豫尝试!