`functools.update_wrapper` 和 `functools.wraps` 复制了比预期更多的属性
`functools.update_wrapper` and `functools.wraps` copy more attributes over than expected
我用了functools.wraps
in a definition of a decorator to forward some attributes of a function to its wrapper. According to the documentation of functools.wraps
, which is based on functools.update_wrapper
,functools.wraps
应该赋值属性,__module__
,__name__
,__qualname__
,__annotations__
,__doc__
,默认情况下,包装函数的包装器。但是,在我自己的用法中,我看到 functools.wraps
也转发我在包装函数中定义的任何属性。
import functools
def decorator(func):
func.added_attr = 'I am added.'
@functools.wraps(func)
def wrapper(*args, **kwargs):
return func(*args, **kwargs)
return wrapper
@decorator
def foo():
pass
print(foo.added_attr)
在上面的例子中,foo
最终引用了定义在decorator
中的包装器,然而这个包装器也有定义在包装函数中的added_attr
。谁能解释文档中未提及的这种行为?
注意:我在 Python 3.7 和 3.8 中测试了上面的代码。
来自 update_wrapper
文档(强调我的):
The default values for these arguments are the module level constants WRAPPER_ASSIGNMENTS
(which assigns to the wrapper function’s __module__
, __name__
, __qualname__
, __annotations__
and __doc__
, the documentation string) and WRAPPER_UPDATES
(which updates the wrapper function’s __dict__
, i.e. the instance dictionary).
func.added_attr = 'I am added.'
更新 func.__dict__
,它被 update_wrapper
复制
我用了functools.wraps
in a definition of a decorator to forward some attributes of a function to its wrapper. According to the documentation of functools.wraps
, which is based on functools.update_wrapper
,functools.wraps
应该赋值属性,__module__
,__name__
,__qualname__
,__annotations__
,__doc__
,默认情况下,包装函数的包装器。但是,在我自己的用法中,我看到 functools.wraps
也转发我在包装函数中定义的任何属性。
import functools
def decorator(func):
func.added_attr = 'I am added.'
@functools.wraps(func)
def wrapper(*args, **kwargs):
return func(*args, **kwargs)
return wrapper
@decorator
def foo():
pass
print(foo.added_attr)
在上面的例子中,foo
最终引用了定义在decorator
中的包装器,然而这个包装器也有定义在包装函数中的added_attr
。谁能解释文档中未提及的这种行为?
注意:我在 Python 3.7 和 3.8 中测试了上面的代码。
来自 update_wrapper
文档(强调我的):
The default values for these arguments are the module level constants
WRAPPER_ASSIGNMENTS
(which assigns to the wrapper function’s__module__
,__name__
,__qualname__
,__annotations__
and__doc__
, the documentation string) andWRAPPER_UPDATES
(which updates the wrapper function’s__dict__
, i.e. the instance dictionary).
func.added_attr = 'I am added.'
更新 func.__dict__
,它被 update_wrapper