When I wrap a function with @
, how do I make the wrapper function look & feel exactly like the wrapped function? help(function)
in particular.<
functools.wraps
can be used to copy the name and docstring of the function. Copying the original function signature is considerably harder to do from scratch.
If you use the third-party decorator module, however, then
import decorator
@decorator.decorator
def wraps(f):
def call(*args, **kw):
print('in', f, args, kw)
return f(*args, **kw)
return call
def g():pass
@wraps
def f(a, b = 1, g = g, *args, **kw):
pass
help(f)
yields
Help on function f in module __main__:
f(a, b=1, g=<function g>, *args, **kw)
I think the other answers are preferable, but if for some reason you don't want to use an external module, you could always alter your decorator like so:
def wraps(f):
def call(*args, **kw):
print('in', f, args, kw)
return f(*args, **kw)
call.__name__ = f.__name__
call.__doc__ = f.__doc__
return call
Use functools.wraps:
from functools import wraps
def wrapper(f):
@wraps(f)
def call(*args, **kw):
print('in', f, args, kw)
return f(*args, **kw)
return call
@wrapper
def f(a, b = 1, g = g, *args, **kw):
pass
help(f)
Help on function f in module __main__:
f(a, b=1, g=<function g at 0x7f5ad14a6048>, *args, **kw)
This preserves the __name__
and __doc__
attributes of your wrapped function.