为什么python decorator会丢失func属性__doc__?

时间:2014-04-15 11:04:41

标签: python decorator

def decor(fun):
    def living(*args, **kw):
        return fun(*args, **kw)
    return living

@decor
def test():
    '''function doc'''
    pass

print test.__doc__

为什么结果为None?我使用装饰器时发生了什么事?谢谢回答!

2 个答案:

答案 0 :(得分:0)

那是因为你的装饰师基本上都在替换你的功能。您需要使用functools.wraps()来存储已装饰的函数内部结构,例如__name____doc__

您可以通过向装饰器函数living()添加docstring来轻松测试:

>>> def decor(fun):
...     def living(*args, **kw):
...         """This is the decorator for living()"""
...         return fun(*args, **kw)
...     return living
... 
>>> @decor
... def test():
...     """function doc"""
...     pass
... 
>>> test.__doc__
'This is the decorator for living()'

保存包装函数名称和文档字符串的functools.wraps()文档示例。

>>> from functools import wraps
>>> def my_decorator(f):
...     @wraps(f)
...     def wrapper(*args, **kwds):
...         print 'Calling decorated function'
...         return f(*args, **kwds)
...     return wrapper
...
>>> @my_decorator
... def example():
...     """Docstring"""
...     print 'Called example function'
...
>>> example()
Calling decorated function
Called example function
>>> example.__name__
'example'
>>> example.__doc__
'Docstring'

答案 1 :(得分:0)

因为当你在装饰器中包装一个函数时:

@decor
def test:

你回来由装饰器创建的函数,在这种情况下(living,在这种情况下),它没有相同的文档字符串,等等。它没有"输"这个数据,living从未有过!

您可以使用functools.wraps来解决此问题:

from functools import wraps

def decor(fun):
    @wraps(fun)
    def living(*args, **kw):
        ...
    return func

快速演示证明这一点:

>>> def wrapper(f):
    def func(*args):
        """The wrapper func's docstring."""
        return f(*args)
    return func

>>> @wrapper
def test(x):
    """The test func's docstring."""
    return x ** 2

>>> test.__doc__
"The wrapper func's docstring."

>>> from functools import wraps
>>> def wrapper(f):
    @wraps(f)
    def func(*args):
        """The wrapper func's docstring."""
        return f(*args)
    return func

>>> @wrapper
def test(x):
    """The test func's docstring."""
    return x ** 2

>>> test.__doc__
"The test func's docstring."