2016-09-21 3 views
0

Kürzlich lerne ich Python Decorator und die Verwendung von functools.wraps.wie __name__ ändern in python dekorator

def a(): 
    def b(): 
     def c(): 
      print('hello') 
     return c 
    return b 


print a.__name__ 
#output:a 

Ich verstehe, warum die Ausgabe a.But Ich weiß nicht, wie __name__ Änderung in dem folgenden Code.

def log(text): 
    def decorator(func): 
     def wrapper(*args, **kw): 
      print('%s %s():' % (text, func.__name__)) 
      return func(*args, **kw) 
     return wrapper 
    return decorator 

@log('...') 
def simple(): 
    print('*' * 20) 

print simple.__name__ 
#output:wrapper 

Warum ist die Ausgabe "Wrapper" und nicht "Dekorateur" oder "Log"?

+0

Vielleicht nicht so verwandt, aber Sie sollten einen Blick auf haben [Was bedeutet' functools.wraps' tun ?] (http://stackoverflow.com/questions/308999/what-does-functools-wraps-do) –

+1

Wissen Sie, wie Dekoratoren intern funktionieren? Das Umschreiben ohne syntaktischen Zucker hilft viel dabei zu verstehen, was hier passiert. –

Antwort

2

Einige Grundlagen:

@decorator 
def f(): 
    pass 

entspricht:

def f(): 
    pass 
f = decorator(f) 

Decorator mit args:

@decorator(*args, **kwargs) 
def f(): 
    pass 

entspricht:

def f(): 
    pass 
decorator_instance = decorator(*args, **kwargs) 
f = decorator_instance(f) 

Mit so kennen, können wir Ihrem Beispiel umschreiben zu:

def simple(): 
    print('*' * 20) 

log_instance = log('...') 
simple = log_instance(simple) 

ist, was letzten beiden Zeilen Lassen Sie analysieren geschieht in:

  • log_instance ist eine decorator Funktion und Textvariablen innerhalb es gleich ' ..."
  • Da decorator (unabhängig von text Wert) Funktion namens Wrapper zurückgibt, wird simple mit Funktion ersetzt namens wrapper
0

Der Punkt der Dekoratoren ist ersetzen eine Funktion oder Klasse mit dem, was durch den Dekorator zurückgegeben wird, wenn mit dieser Funktion/Klasse als Argument aufgerufen. Decorators mit Argumenten sind ein bisschen mehr verschachtelt, wie Sie zuerst die äußere Methode (log) aufrufen, um einen "parametrisierten" Decorator (decorator) zu erhalten, dann rufen Sie diese und erhalten die letzte Funktion (wrapper), die die verzierte Funktion ersetzen wird (simple).

Also, es eine gewisse Struktur zu geben,

  1. Aufruf log mit '...' als Argument und erhalten decorator
  2. Aufruf decorator mit simple als Argument und erhalten wrapper
  3. ersetzen simple mit wrapper
0
@log('...') 
def simple(... 

entspricht

def simple(... 
simple = log('...')(simple) 

so log wird tatsächlich aufgerufen, Return decorator, die mit simple als Argument aufgerufen wird, die dann durch decorator ‚s Rückgabewert ersetzt wird, die die Funktion ist wrapper, damit seine __name__ ist wrapper.

Verwandte Themen