处理docstring的Python装饰器
我在装饰程序中使用docstring时遇到问题。给出以下示例:处理docstring的Python装饰器,python,decorator,docstring,Python,Decorator,Docstring,我在装饰程序中使用docstring时遇到问题。给出以下示例: def decorator(f): def _decorator(): print 'decorator active' f() return _decorator @decorator def foo(): '''the magic foo function''' print 'this is function foo' help(foo) 现在,帮助没有按预期
def decorator(f):
def _decorator():
print 'decorator active'
f()
return _decorator
@decorator
def foo():
'''the magic foo function'''
print 'this is function foo'
help(foo)
现在,帮助没有按预期显示foo
的docstring,它显示:
Help on function _decorator in module __main__:
_decorator()
如果没有decorator,则帮助是正确的:
Help on function foo in module __main__:
foo()
the magic foo function
我知道,函数
foo
是由decorator包装的,因此函数对象不再是函数foo
。但是,要获得预期的文档字符串(以及帮助),什么是好的解决方案呢?我找到了一个解决方案,但不知道它是否真的好:
def decorator(f):
def _decorator():
print 'decorator active'
f()
_decorator.__name__=f.__name__
_decorator.__doc__=f.__doc__
return _decorator
带有\u decorator.\uuuuuuu name\uuuuuu=f.\uuuuu name\uuuuuuu
的部分看起来有点可怕。。。您认为如何?使用functools.wrapps()
更新装饰器的属性:
from functools import wraps
def decorator(f):
@wraps(f)
def _decorator():
print 'decorator active'
f()
return _decorator
@decorator
def foo():
'''the magic foo function'''
print 'this is function foo'
help(foo)
另请参见for
functools
查看functools.wrapps
:如果foo
接受任何参数,则这不起作用-它们将被\u decorator
使用的任何参数替换。这是一个问题,尤其是当您希望您的装饰者使用*args、**kwds
时。我一直无法找到使用functools.wrapps
@Scott Griffiths获得正确文档字符串的方法:即使foo
使用参数,文档字符串仍然是正确的。但是,help(foo)
将显示\u decorator
的参数列表,因为它实际上替换了foo
函数。如果您正在编写使用*args、**kwargs
接受任意参数的修饰符,那么没有好办法解决这个问题,但对我来说,重要的一点是docstring保持完整。为了清晰起见,可以在docstring中指定参数详细信息。感谢提供额外信息。最近,我一直未能获得装饰函数的正确帮助描述-这似乎是一个相当糟糕的状态,但我理解困难,因为装饰函数可能具有完全不同的签名。不过,一定有办法……:)有一种方法可以做到这一点。decorator模块通过使用技巧来实现这一点。诀窍是重新生成decorator签名并在其上运行exec。您可以在decorator.py的第118行中找到诀窍。然而,我认为这种方法是极端的。看来functools.wrapps现在确实可以使help()
正常工作。我很难找到这是什么时候改变的,但我仍然在使用Python2.7。快乐的一天!事实上,这(几乎?)正是functools.wrapps所做的:)在我看来并不可怕。它说的正是你想要它说的。“我希望这个函数的名称是‘myfunction’,而不是‘装饰者’。”你不应该重新发明轮子,特别是当标准库中有一个工作函数可以实现这一点时,经过良好测试、维护和记录。我不能与@Azat Ibrakov一起使用;我总是喜欢一个清晰易读的解决方案,它不依赖于任何库(最终也会改变)。因此,我真的很喜欢这种简单直接的方法(+1)。此外,此解决方案不会复制f
(如果有)和返回类型的参数的docstring<代码>functools.wrapps可执行此操作。