2009-12-27 152 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."