2008-12-04 5 views
5

Als BeispielPython Decorators vor Funktion ausgeführt wird es heißt dekorieren?

def get_booking(f=None): 
    print "Calling get_booking Decorator" 
    def wrapper(request, **kwargs): 
     booking = _get_booking_from_session(request) 
     if booking == None: 
      # we don't have a booking in our session. 
      return HttpRedirect('/') 
     else: 
      return f(request=request, booking=booking, **kwargs) 
    return wrapper 

@get_booking 
def do_stuff(request, booking): 
    # do stuff here 

Das Problem, das ich habe ist, wird die @get_booking Dekorateur, noch bevor ich die Funktion, dass ich die Dekoration am genannt genannt wird.

Ausgabe am Start:

Calling get_booking Decorator 
Calling get_booking Decorator 
Calling get_booking Decorator 
Calling get_booking Decorator 
Calling get_booking Decorator 
Calling get_booking Decorator 
Calling get_booking Decorator 
Calling get_booking Decorator 
Calling get_booking Decorator 
Calling get_booking Decorator 
[26/Oct/2008 19:54:04] "GET /onlinebooking/?id=1,2 HTTP/1.1" 302 0 
[26/Oct/2008 19:54:05] "GET /onlinebooking/ HTTP/1.1" 200 2300 
[26/Oct/2008 19:54:05] "GET /site-media/css/style.css HTTP/1.1" 200 800 
[26/Oct/2008 19:54:05] "GET /site-media/css/jquery-ui-themeroller.css HTTP/1.1" 200 25492 

Ich habe nicht einmal einen Anruf an eine Funktion aus, die an dieser Stelle eingerichtet.

Ich fange gerade mit Dekorateuren an, also verpasse ich vielleicht etwas. Irgendeine Hilfe?

+0

Um den Fragetitel direkt zu beantworten, ** Läuft ein Dekorateur vor der dekorierten Funktion? **. Nein, es wird nicht ausgeführt, wenn die Funktion deklariert wird. Es wird ausgeführt, wenn die Funktion _called_ ist. Ich hoffe das hilft. – Jess

Antwort

25

Ich glaube, Python Dekorateure sind nur syntaktischer Zucker.

@foo 
def bar(): 
    pass 

ist das gleiche wie

def bar(): 
    pass 
bar = foo(bar) 

Wie Sie sehen können, foo genannt wird, obwohl bar nicht aufgerufen wurde. Aus diesem Grund sehen Sie die Ausgabe Ihrer Decorator-Funktion. Ihre Ausgabe sollte eine einzelne Zeile für jede Funktion enthalten, auf die Sie Ihren Decorator angewendet haben.

0

Ein Dekorator wird aufgerufen, sobald die dekorierte Funktion definiert ist. Es ist gleichwertig, so etwas zu schreiben:

def __do_stuff(...): 
    ... 

do_stuff = get_booking(__do_stuff) 
0

Python Dekorateure Funktionen auf eine Funktion angewendet werden, um es zu transformieren:

@my_decorator 
def function(): ... 

ist wie dies zu tun:

def function():... 
function = my_decorator(function) 

Was Sie wollen, zu tun ist:

def get_booking(f=None): 
    def wrapper(request, **kwargs): 
     print "Calling get_booking Decorator" 
     booking = _get_booking_from_session(request) 
     if booking == None: 
      # we don't have a booking in our session. 
      return HttpRedirect('/') 
     else: 
      return f(request=request, booking=booking, **kwargs) 
    return wrapper 
+0

Was bringt ein Vorgabewert für die Zielfunktion in einem Decorator? – muhuk

+0

Zumal es nie auf None überprüft wurde. – Dan

+0

Ich weiß nicht wirklich, was ist seine Absicht, ich dachte, es war eher für die Weiterleitung. –

2

Da Sie mit Dekorateuren beginnen, denke ich, dass das Lesen hilfreich ist, damit Sie die Fallstricke und Problemumgehungen im Voraus kennen.

Hier sind zwei Links zu früheren Diskussionen über Dekorateure.

Python decorator makes function forget that it belongs to a class What does functools.wraps do?

Darüber hinaus ist die zweite Verbindung erwähnt ‚functools‘ ein Modul für die Funktionen höherer Ordnung, die auf wirken oder andere Funktionen geben. Die Verwendung von functools.wraps wird empfohlen, da die Doc-Zeichenkette der ursprünglichen Funktion beibehalten wird (dekoriert).

Ein anderes Problem war falsche Methodensignaturen beim Generieren von automatischen Dokumenten für mein Projekt. aber es gibt eine Problemumgehung: Preserving signatures of decorated functions

Ich hoffe, dies hilft.

Verwandte Themen