Python decorator with arguments to the decorated function

When I wrap a function with @ , how do I make the wrapper function look and feel just like a wrapped function? help(function) in particular.

Some codes:

 >>> def wraps(f): def call(*args, **kw): print('in', f, args, kw) # example code. I need to transfer the arguments to another process and pickle them. return f(*args, **kw) return call >>> def g():pass >>> @wraps def f(a, b = 1, g = g, *args, **kw): pass >>> help(f) Help on function call in module __main__: call(*args, **kw) # this line bothers me. It should look different, look below >>> 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 0x02EE14B0>, *args, **kw) # help(f) should look like this. 

Motivation. It would be nice to see the arguments when the help window appears, when I type f( * plopp *, I see (a, b = 1, g = g, *args, **kw) . (In this case, in the Python IDLE shell)

I looked at the inspect module, which helps me with good formatting. The problem still exists: how do I do this with the arguments.

Passing arguments to a mutable default value like def f(d = {}): should not work, because I pass arguments to another process, and in any case, the loss will be lost.

+2
python
May 31 '14 at 18:59
source share
3 answers

functools.wraps can be used to copy name and docstring functions. Copying the original function signature is much harder to do from scratch.

If you are using a third-party decorator module , 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) 

gives

 Help on function f in module __main__: f(a, b=1, g=<function g>, *args, **kw) 
+3
May 31 '14 at 19:25
source share
— -

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 saves the __name__ and __doc__ your wrapped function.

+2
May 31 '14 at 19:15
source share

I think other answers are preferable, but if for some reason you do not want to use an external module, you can always change your decorator as follows:

 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 
0
May 31 '14 at 10:42
source share



All Articles