Приятная вещь Python заключается в том, что он имеет набор правил для передачи своих объектов и очень мало исключений из этих правил.
В этом случае функция, которая украшена, является обычным объектом Python. Тот, который также может быть вызван.
Что происходит в линии wrapper.all_input = []
внутри collect_input является то, что он устанавливает атрибут на объекте - в этой точке под названием wrapper
- но это объект, который будет возвращен и занять место функции foo
в глобальном масштабе. Вот как работают декораторы.
Так давайте есть корыто, шаг за шагом, чтобы сделать его как можно более ясно:
При выполнении кода выше, определяет collect_input
функцию - которая предназначена для использования в качестве декоратора.
Затем он определяет функцию foo
, но перед ее добавлением в глобальную область она передается в функцию collect_input
. Вот что делает синтаксис «@». До его существования способ украсить функции, чтобы сначала определить функцию, а затем заменить ее для возвращаемого значения декоратора с нормальным назначением. Таким образом, приведенный выше код такой же, как:
четкости Foo (...): ...
обув = collect_input (Foo)
Внутри "collect_input", оригинальный foo
FUNC будет вызываться внутри новой функции wrapper
. Эта функция wrapper
: новый (функциональный) объект, созданный каждый раз, когда вызывается декоратор collect_input
, является объектом, который заменит самое внешнее определение foo
. Вы можете видеть, что внутри кода для wrapper
есть дополнительный код для того, чтобы сделать то, что означает collect_input
: аннотировать входные параметры в списке, прикрепленный к нему, а затем возобновить вызов исходной функции - foo
в этом случае.
Наконец wrapper
объект, который возвращается collect_input
занимает место foo
, но имеет all_inputs
список прилагается к нему внутри вызова декоратора. Таким образом, он может быть доступен в глобальной области как атрибут объекта foo
- независимо от того, где он был определен. Обратите внимание, что вы не можете, вне функции, использовать имена func
или wrapper
, как и ожидалось.
На самом деле, вы не доступ к '' foo.all_input' но wrapper.all_input' потому, что вы завернуты вашей функция с декораторой который возвращает функцию 'wrapper'. – Kasramvd