Подтвердить что ты не робот

Порядок выполнения декоратора

def make_bold(fn):
    return lambda : "<b>" + fn() + "</b>"

def make_italic(fn):
    return lambda : "<i>" + fn() + "</i>"

@make_bold
@make_italic
def hello():
  return "hello world"

helloHTML = hello()

Выход: "<b><i>hello world</i></b>"

Я почти понимаю о декораторах и как он работает с одним из них в большинстве примеров.

В этом примере их 2. Из вывода кажется, что @make_italic выполняется сначала, а затем @make_bold.

Означает ли это, что для украшенных функций сначала будет запускаться функция, а затем двигаться к вершине для других декораторов? Как и @make_italic сначала, а затем @make_bold вместо противоположного.

Значит, это означает, что он отличается от нормы подхода сверху вниз в большинстве программных языков? Только для этого случая декоратора? Или я ошибаюсь?

4b9b3361

Ответ 1

Декораторы обертывают функцию, которую они украшают. Итак, make_bold украсил результат декодера make_italic, который украсил функцию hello.

Синтаксис @decorator - это действительно просто синтаксический сахар; следующее:

@decorator
def decorated_function():
    # ...

действительно выполняется как:

def decorated_function():
    # ...
decorated_function = decorator(decorated_function)

заменив исходный объект decorated_function на все decorator().

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

Итак, ваш образец:

@make_bold
@make_italic
def hello():
  return "hello world"

можно расширить до:

def hello():
  return "hello world"
hello = make_bold(make_italic(hello))

Когда вы вызываете hello() сейчас, вы вызываете объект, возвращенный make_bold(), действительно. make_bold() возвращает a lambda, который вызывает функцию make_bold wrapped, которая является возвращаемым значением make_italic(), которое также является лямбдой, которая вызывает исходный hello(). Расширяя все эти вызовы, вы получаете:

hello() = lambda : "<b>" + fn() + "</b>" #  where fn() ->
    lambda : "<i>" + fn() + "</i>" # where fn() -> 
        return "hello world"

поэтому выход будет выглядеть следующим образом:

"<b>" + ("<i>" + ("hello world") + "</i>") + "</b>"

Ответ 2

Я использую Flask в качестве микро-фреймворка для производственного API, который я создаю. Я понимаю порядок декораторов методов и почему, но, как ни странно, мне пришлось изменить порядок (потому что это важно) моих декораторов из-за того, когда они выполняются. К моему удивлению, декораторы работали не в обычном порядке, а в обратном порядке. Другими словами, декораторы выполняются сверху вниз, спускаясь к оператору def. Это продолжало сбивать меня с толку, потому что декораторы, которые я ожидал запустить первыми, внизу возле def, фактически работали последними, и наоборот. Кто-нибудь видел это, и есть ли что-то в структуре Flask, что мешает с заказом? Я был бы удивлен, поскольку Flask, кажется, придерживается правил и духа Python, но мне странно, когда я вижу, что что-то фундаментальное работает не так, как ожидалось.