Декоратор Python, обрабатывающий docstrings

У меня проблема с использованием docstrings с декораторами. В следующем примере:

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)

Теперь помощь не показывает мне docstring foo, как и ожидалось, она показывает:

Help on function _decorator in module __main__:

_decorator()

Без декоратора помощь верна:

Help on function foo in module __main__:

foo()
    the magic foo function

Я знаю, что функция foo обернута декоратором, поэтому объект функции больше не является функцией foo. Но что хорошего решения для получения docstring (и помощи), как ожидалось?

Ответ 1

Используйте functools.wraps() для обновления атрибутов декоратора:

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)

Также см. Документацию по стандартной библиотеке для functools.

Ответ 2

Я нашел решение, но не знаю, действительно ли это приятно:

def decorator(f):
    def _decorator():
        print 'decorator active'
        f()
    _decorator.__name__=f.__name__
    _decorator.__doc__=f.__doc__
    return _decorator

Часть с _decorator.__name__=f.__name__ кажется немного отвратительной... Как вы думаете?

Ответ 4

Это, наверное, немного устарело, но так вы это делаете. Просто убедитесь, что @decorator имеет отступ в той же строке, что и def decorator(f):

from functools import wraps

def decorator(f):
    @wraps(f)
    def _decorator():
        print 'decorator active'
        return f()
    return _decorator

@decorator
def foo():
    '''the magic foo function'''
    print 'this is function foo'

help(foo)