简体   繁体   English

带装饰函数参数的python decorator

[英]python decorator with arguments of decorated function

When I wrap a function with @ , how do I make the wrapper function look & feel exactly like the wrapped function? 当我用@包装函数时,如何使包装函数的外观和感觉完全像包装函数一样? help(function) in particular. 特别是help(function)

Some code: 一些代码:

>>> 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 also be nice to see the arguments when the help window pops up, when I type f( * plopp * I see (a, b = 1, g = g, *args, **kw) . (in this case in the IDLE Python Shell) 动机:当我输入帮助窗口,当我输入f( * plopp *我看到(a, b = 1, g = g, *args, **kw)时,看到参数也会很高兴。(在此IDLE Python Shell中的case

I had a look at the inspect module which helps me with nice formatting. 我看了一下inspect模块,它帮助我进行了很好的格式化。 The problem is still there: how do I do this with arguments.. 问题仍然存在:我如何用参数做到这一点..

Default mutable argument passing like def f(d = {}): does not need to work since I transfer the arguments to another process and the identity would be lost anyway. def f(d = {}):一样传递的默认可变参数def f(d = {}):不需要工作,因为我将参数传递给另一个进程,无论如何身份都会丢失。

functools.wraps can be used to copy the name and docstring of the function. functools.wraps可用于复制函数的名称和docstring。 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)

Use functools.wraps : 使用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. 这会保留包装函数的__name____doc__属性。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM