如何将装饰器中的变量传递给装饰函数中的函数参数?

Jap*_*boy 31 python decorator

我正在学习Python.希望有人指出我正确的方式.
这就是我想在下面做的事情:

def decorate(function):
    def wrap_function(*args, **kwargs):
        str = 'Hello!'  # This is what I want
        return function(*args, **kwargs)
    return wrap_function

@decorate
def print_message():
    # I'd like to pass 'str' as mentioned above
    # to any functions' argument like below:
    print(str)  # 'str' is same as above
Run Code Online (Sandbox Code Playgroud)

任何的想法?提前致谢.

Tor*_*amo 46

您不能将其作为自己的名称传递,但可以将其添加到关键字中.

def decorate(function):
    def wrap_function(*args, **kwargs):
        kwargs['str'] = 'Hello!'
        return function(*args, **kwargs)
    return wrap_function

@decorate
def print_message(*args, **kwargs):
    print(kwargs['str'])
Run Code Online (Sandbox Code Playgroud)

或者,您可以命名自己的参数:

def decorate(function):
    def wrap_function(*args, **kwargs):
        str = 'Hello!'
        return function(str, *args, **kwargs)
    return wrap_function

@decorate
def print_message(str, *args, **kwargs):
    print(str)
Run Code Online (Sandbox Code Playgroud)

分类方法:

def decorate(function):
    def wrap_function(*args, **kwargs):
        str = 'Hello!'
        args.insert(1, str)
        return function(*args, **kwargs)
    return wrap_function

class Printer:
    @decorate
    def print_message(self, str, *args, **kwargs):
        print(str)
Run Code Online (Sandbox Code Playgroud)

  • 请注意,第一个解决方案也是通过使用`functools.partial()`实现的(但仅限于2.6版本).同一个模块还提供了`wraps()`函数,可以与装饰器一起使用来保持原始函数的名称和文档. (4认同)

Vla*_*ius 12

如果你想让参数"可选地注入",只有在函数真正接受它的情况下,使用这样的东西:

import inspect

def decorate(func):
    def wrap_and_call(*args, **kwargs):
        if 'str' in inspect.getargspec(func).args:
            kwargs['str'] = 'Hello!'
        return func(*args, **kwargs)
    return wrap_and_call

@decorate
def func1(str):
    print "Works! - " + str

@decorate
def func2():
    print "Should work, also."
Run Code Online (Sandbox Code Playgroud)

  • 请注意,不建议使用getargspec。对于Python3,请使用[getfullargspec](https://docs.python.org/3/library/inspect.html#inspect.getfullargspec)。 (4认同)