2008-12-04 9 views
5

A modo de ejemplo,Los decoradores de Python se ejecutan antes de la función que se llama decorar?

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 

El problema que estoy teniendo es, el decorador @get_booking se está llamando incluso antes de llamar a la función que estoy decorando.

salida en el arranque:

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 

ni siquiera he hecho una llamada a una función que está decorado en este punto.

Estoy empezando con los decoradores, así que tal vez me falta algo. ¿Alguna ayuda?

+0

Para responder al título de la pregunta directamente, ** ¿Se ejecuta un decorador antes de la función decorada? **. No, no se ejecuta cuando se declara la función. Se ejecuta cuando la función se llama _. Espero que esto ayude. – Jess

Respuesta

25

Creo que los decoradores de pitón son solo azúcar sintáctico.

@foo 
def bar(): 
    pass 

es lo mismo que

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

Como se puede ver, foo se está llamando a pesar de que la barra no ha sido llamado. Es por eso que ve la salida de su función de decorador. Su salida debe contener una sola línea para cada función que haya aplicado a su decorador.

0

Se llama a un decorador tan pronto como se define la función decorada. Es equivalente a escribir algo como esto:

def __do_stuff(...): 
    ... 

do_stuff = get_booking(__do_stuff) 
0

decoradores de Python son funciones aplicadas a una función para transformarla:

@my_decorator 
def function(): ... 

es como hacer esto:

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

lo que quieres hay que hacer es:

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

¿De qué sirve dar un valor predeterminado para la función objetivo en un decorador? – muhuk

+0

Especialmente porque nunca se marcó para None. – Dan

+0

Realmente no sé cuál es su propósito, pensé que era más bien para la redirección. –

2

Dado que está empezando con decoradores, creo que leer estos será útil, para que conozca las trampas y soluciones de antemano.

Aquí hay dos enlaces a discusiones anteriores sobre decoradores.

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

Además, el segundo enlace menciones 'functools' un módulo para funciones de orden superior, que actúan sobre o devuelven otras funciones. Se recomienda el uso de functools.wraps ya que conserva la cadena de documentación de la función original (decorada).

Otro problema fueron las firmas de métodos incorrectos al generar documentos automáticos para mi proyecto. pero hay una solución alternativa: Preserving signatures of decorated functions

Espero que esto ayude.

Cuestiones relacionadas