Python Decorators запускаются до того, как вызывается функция, которую он украшает?

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

  •  19-08-2019
  •  | 
  •  

Вопрос

В качестве примера,

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

У меня проблема в том, что декоратор @get_booking вызывается еще до того, как я вызвал функцию, которую я декорирую.

Вывод при запуске:

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

Я даже не вызывал функцию, которая оформлена на данный момент.

Я только начинаю с декораторами, так что, может быть, я что-то упустил. Любая помощь?

Это было полезно?

Решение

Я считаю, что декораторы Python - это просто синтаксический сахар.

@foo
def bar ():
    pass

это то же самое, что и

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

Как видите, foo вызывается, хотя bar не вызывался. Вот почему вы видите результат работы вашей функции декоратора. Ваш вывод должен содержать одну строку для каждой функции, к которой вы применили декоратор.

Другие советы

Поскольку вы начинаете с декораторов, я думаю, что их чтение будет полезно, так что вы заранее знаете подводные камни и обходные пути.

Вот две ссылки на предыдущие обсуждения декораторов.

Python decorator заставляет функцию забыть что он принадлежит классу Что делает functools.wraps?

Кроме того, во второй ссылке упоминается «functools» модуль для функций высшего порядка, которые действуют или возвращают другие функции. Рекомендуется использовать functools.wraps, поскольку он сохраняет строку документа исходной функции (оформленной).

Другая проблема заключалась в неправильных сигнатурах методов при создании автоматических документов для моего проекта. но есть обходной путь: Сохранение подписей оформленных функций

Надеюсь, это поможет.

Декоратор вызывается, как только определена декорированная функция. Это эквивалентно написанию чего-то вроде этого:

def __do_stuff(...):
    ...

do_stuff = get_booking(__do_stuff)

Python-декораторы - это функции, применяемые к функции для ее преобразования:

@my_decorator
def function (): ...

это как делать это

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

То, что вы хотите сделать, это:

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
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top