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 solu开发者_如何学运维tion to get the docstring (and the help) as expected?
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
.
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?
Take a look at functools.wraps
: http://docs.python.org/library/functools.html
The solution is pretty easy. The doc string should be mentioned in the top most decorator that is being called on top of the main function. Find the example below:
import math
def wrap2(func):
def squarer(x):
return [math.sqrt(i) for i in func(x)]
return squarer
def wrap1(func):
def summer(x):
return [i*2 for i in func(x)]
return summer
def wrap3(func):
def rounder(x):
return [round(i,1) for i in func(x)]
return rounder
def wrap4(func):
def stringer(x):
'''
Enter the input of a 2-dim array to get the output
'''
return [str(i)+' rounds ' for i in func(x)]
return stringer
@wrap4
@wrap3
@wrap2
@wrap1
def rooter(i):
return [sum(p) for p in i]
help(rooter)
# output
Help on function stringer in module __main__:
stringer(x)
Enter the input of a 2-dim array to get the output
---or----
Signature: rooter(x)
Docstring: Enter the input of a 2-dim array to get the output
File: d:\<ipython-input-392-487fc73b05cf>
Type: function
So, the Doc String must be mentioned in the wrap4 decorator function for it to be visible in the main function.
精彩评论