Les décorateurs Python s'exécutent avant que la fonction de décoration ne soit appelée?

StackOverflow https://stackoverflow.com/questions/341379

  •  19-08-2019
  •  | 
  •  

Question

À titre d'exemple,

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

Le problème que je rencontre est que le décorateur @get_booking est appelé avant même que j'appelle la fonction que je décore.

Sortie au démarrage:

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

Je n'ai même pas fait appel à une fonction décorée à ce stade.

Je commence tout juste avec les décorateurs, alors peut-être que quelque chose me manque. Toute aide?

Était-ce utile?

La solution

Je crois que les décorateurs en python ne sont que du sucre syntaxique.

@foo
def bar ():
    pass

est la même chose que

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

Comme vous pouvez le constater, toto est appelé même si bar n'a pas été appelé. C'est pourquoi vous voyez le résultat de votre fonction de décorateur. Votre sortie doit contenir une seule ligne pour chaque fonction à laquelle vous avez appliqué votre décorateur.

Autres conseils

Puisque vous commencez avec des décorateurs, je pense que leur lecture vous aidera à connaître les pièges et les solutions de rechange à l'avance.

Voici deux liens vers des discussions précédentes sur les décorateurs.

Un décorateur Python supprime la fonction qu'il appartient à une classe Que fait functools.wraps?

De plus, le second lien mentionne "functools", un module pour les fonctions d'ordre supérieur, qui agit sur ou retourne d'autres fonctions. L'utilisation de functools.wraps est conseillée car elle conserve la doc string de la fonction d'origine (décorée).

Un autre problème était la mauvaise signature des méthodes lors de la génération de documents automatiques pour mon projet. mais il existe une solution de contournement: Conservation des signatures des fonctions décorées

J'espère que cela vous aidera.

Un décorateur est appelé dès que la fonction décorée est définie. Cela équivaut à écrire quelque chose comme ceci:

def __do_stuff(...):
    ...

do_stuff = get_booking(__do_stuff)

Les décorateurs Python sont des fonctions appliquées à une fonction pour la transformer:

@my_decorator
def function (): ...

est comme faire ceci:

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

Ce que vous voulez faire est:

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
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top