2009-12-27 26 views
23

Jestem w trakcie nauki Pythona. Mam nadzieję, że ktoś wskazuje mi na poprawny sposób.
To, co chciałbym zrobić poniżej:Jak mogę przekazać zmienną w dekoratorze do argumentu funkcji w dekorowanej funkcji?

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 

jakiś pomysł? Z góry dziękuję.

Odpowiedz

30

Nie można przekazać go jako własnego, ale można go dodać do słów kluczowych.

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

Alternatywnie można nazwać swój własny argument:

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) 

metoda klasy:

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

Zauważ, że pierwsze rozwiązanie jest również osiągnięte przez użycie 'functools.partial()' (ale tylko z wersji 2.6). Ten sam moduł oferuje również funkcję 'wraps()', która może być używana z dekoratorami w celu zachowania nazwy i dokumentu oryginalnej funkcji. – RedGlyph

+0

@RedGlyph: dlaczego używamy 'functools.partial()' tylko z wersji 2.6? dokumentacja nic nie mówi, poza tym, że moduł functools jest nowy w pyhtonie 2.5. –

+0

Podziękowania dla Tora Valamo. Alternatywne rozwiązanie jest dla mnie jasne. Ale co powiesz na to, czy dekorowana funkcja jest metodą instancji? Argument metody instancji powinien wyglądać tak: 'def print_message (str, self, * args, ** kwargs):' Czy to jest poprawne? Dzięki jeszcze raz. – Japboy

5

Jeśli chcesz argument za "ewentualnie wtryskiem", tylko w przypadku funkcji faktycznie bierze to, użyj czegoś takiego:

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." 
Powiązane problemy