Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python decorator handling docstrings

I have a problem using docstrings with decorators. Given the following example:

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)

Now the help doesn't show me the docstring of foo as expected, it shows:

Help on function _decorator in module __main__:

_decorator()

Without the decorator, the help is correct:

Help on function foo in module __main__:

foo()
    the magic foo function

I know, that the function foo is wrapped by the decorator, and so the function object is not the function foo any more. But what is a nice solution to get the docstring (and the help) as expected?

like image 501
Günther Jena Avatar asked Nov 23 '09 12:11

Günther Jena


People also ask

Should I use docstrings in Python?

All modules should normally have docstrings, and all functions and classes exported by a module should also have docstrings. Public methods (including the __init__ constructor) should also have docstrings. A package may be documented in the module docstring of the __init__.py file in the package directory.

How do you access docstrings in Python?

Accessing Docstrings: The docstrings can be accessed using the __doc__ method of the object or using the help function.

How do you access docstrings of a function?

Docstrings are accessible from the doc attribute (__doc__) for any of the Python objects and also with the built-in help() function. An object's docstring is defined by including a string constant as the first statement in the object's definition.

Where do you put docstrings?

Module docstrings are placed at the top of the file even before any imports. Module docstrings should include the following: A brief description of the module and its purpose. A list of any classes, exception, functions, and any other objects exported by the module.


3 Answers

Use functools.wraps() to update the attributes of the decorator:

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)

Also see the Standard Library documentation for functools.

like image 128
Pär Wieslander Avatar answered Oct 13 '22 18:10

Pär Wieslander


I found a solution, but don't know if it's really nice:

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

The part with _decorator.__name__=f.__name__ seems a little bit hideous... What do you think?

like image 32
Günther Jena Avatar answered Oct 13 '22 17:10

Günther Jena


Take a look at functools.wraps: http://docs.python.org/library/functools.html

like image 4
Mark Byers Avatar answered Oct 13 '22 17:10

Mark Byers