本文翻译自Stackoverflow:What does functools.wraps do?
当你使用一个装饰器,就是用另一个函数替换当前函数。换一种说法,如果你有一个装饰器:
1 | def logged(func): |
你这样使用它:
1 | @logged |
实际上和这种用法相同:
1 | def f(x): |
而且你的函数 f
被 with_loging
替换。不幸的是,这意味着当你使用:
1 | print f.__name___ |
它会打印出 with_logging
因为这是你新函数的名字。事实上,如果你查看 f
的 文档字符串,它将是空的,因为 with_logging
没有文档字符串所以你写的文档字符串不会在这里出现。并且,如果你查看这个函数使用 pydoc
生成结果,他的参数列表不是一个参数 x
,取而代之的是 *args
和 **kwargs
因为这是 with_logging
所持有的。
如果使用装饰器总是意味着丢失这个函数的信息,这将是个严重的问题。这就是为什么我们有 functools.wraps
的原因。给函数使用一个装饰器并且给函数增加复制名字、文档字符串、参数列表等功能性(This takes a function used in a decorator and adds the functionality of copying over the function name, docstring, arguments list, etc)。当 wraps
是它自己的装饰器,下边的代码将会做正确的事情。
1 | from functools import wraps |