Закрытие и Декоратор - PullRequest
       37

Закрытие и Декоратор

0 голосов
/ 04 апреля 2020

Я только что обнаружил, что декоратор - это один из способов вложения функций, и я натолкнулся на этот специфический случай с концепцией, называемой «замыканием». В основном это означает, что вложенная функция имеет доступ к внешней области видимости вмещающей функции. Это выглядит достаточно интуитивно, пока я не нашел этот фрагмент кода следующим образом:

def decorator_with_arguments(function):
   "this decorator actually takes a real function as input"
    def wrapper_accepting_arguments(arg1,arg2):
        print("My arguments are: {0},{1}".format(arg1,arg2))
        function(arg1,arg2)
    return wrapper_accepting_arguments

@decorator_with_arguments
def cities(city_one,city_two):
    print("Cities I love are {0} and {1}".format(city_one,city_two))
cities("Beijing","Chicago")

Вывод будет следующим:

My arguments are: Bejing,Chicago
Cities I love are Bejing and Chicago

У меня есть два вопроса относительно этого фрагмента кода. Прежде всего, не удивительно ли, что функция wrapper_accepting_arguments понимает, что arg1 и arg2 происходят из функции и выводят их определенным образом, прежде чем она получит доступ к function(arg1,arg2)? Разве Python интерпретатор не читает строку за строкой? Я понимаю, что когда вы применяете несколько декораторов к функции, скажем, у вас есть два @ вместе с функцией, тогда сначала будет оправдан символ @ внизу. Но в теле функции, почему она читается в обратном направлении?

Второй вопрос: если вы удалите строку function(arg1,arg2) (как я пытался понять, что она делает), вывод будет следующим образом,

My arguments are: Beijing,Chicago

, как если бы вы никогда не вызывали функцию «городов», определенную внизу. почему это так?

Это вместе с рекурсией работает чудесным образом. Это, конечно, не линейно или сверху вниз.

Большое спасибо! Любой указатель будет очень признателен!

1 Ответ

1 голос
/ 06 апреля 2020

В тот момент, когда этот код

@decorator_with_arguments
def cities(city_one,city_two):
    print("Cities I love are {0} and {1}".format(city_one,city_two))

импортируется, вызывается функция decorator_with_arguments с функцией cities в качестве параметра. Это немедленно вернет вашу внутреннюю функцию wrapper_accepting_arguments, которая фактически заменит определение def cities.

Так что когда вы затем вызываете cities("Beijing","Chicago"), она фактически вызывает эту внутреннюю функцию wrapper_accepting_arguments с аргументами "Beijing","Chicago". Это приведет к выводу My arguments are: Beijing,Chicago с последующим вызовом исходного определения cities (которое было сохранено в замыкании), что приведет к печати Cities I love are Beijing and Chicago.

...