当我使用@
包装函数时,如何使包装函数看起来&感觉就像包裹的功能?特别是help(function)
。
一些代码:
>>> 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.
动机:当我弹出帮助窗口,当我输入f(
* plopp *我看到(a, b = 1, g = g, *args, **kw)
时,看到参数也会很高兴。 (在这种情况下,在IDLE Python Shell中)
我查看了inspect
模块,它帮助我进行了很好的格式化。问题仍然存在:如何使用参数进行此操作..
像def f(d = {}):
这样的默认可变参数传递不需要工作,因为我将参数传递给另一个进程,无论如何身份都会丢失。
答案 0 :(得分:3)
functools.wraps
可用于复制函数的名称和docstring。从头开始复制原始功能签名要困难得多。
但是,如果您使用第三方decorator module,那么
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)
产量
Help on function f in module __main__:
f(a, b=1, g=<function g>, *args, **kw)
答案 1 :(得分:2)
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)
这会保留包装函数的__name__
和__doc__
属性。
答案 2 :(得分:0)
我认为其他答案更可取,但如果由于某种原因您不想使用外部模块,您可以随时更改装饰器:
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