2009-12-27 150 views
23

我正在学习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 

任何想法?提前致谢。

回答

30

你不能把它作为自己的名字,但你可以将其添加到关键字。

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']) 

或者你能说出自己的论点:

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) 

类方法:

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) 
+4

请注意,第一个解决方案也是通过使用'functools.partial()'(但仅限于2.6版本)来实现的。同样的模块还提供'wrapps()'函数,可以用于装饰器来维护原始函数的名称和文档。 – RedGlyph 2009-12-27 10:24:32

+0

@RedGlyph:为什么只使用'functools.partial()'2.6版本?除了functools模块是pyhton 2.5中的新增功能外,文档中没有提到任何内容。 – 2009-12-27 10:49:36

+0

感谢Tor Valamo。替代解决方案对我来说很明显。但是如果装饰的函数是一个实例方法呢?实例方法的参数应该是这样的:'def print_message(str,self,* args,** kwargs):'这是正确的吗?再次感谢。 – Japboy 2009-12-27 11:41:48

5

如果你想在一个参数是“任选注入”,只有在情况下,函数其实需要它,使用这样的:

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."