Главное свойство декораторов – то, что они выполняются сразу после определения декорируемой функции. Обычно на этапе импорта то есть когда Python загружает модуль.
Рассмотрим скрипт registration.py в примере №1.
Пример №1. Модуль registration.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
registry = [] # (1) def register(func): # (2) print("running register(%s)" % func) # (3) registry.append(func) # (4) return func # (5) @register # (6) def f1(): print("running f1()") @register def f2(): print("running f2()") def f3(): # (7) print("running f3()") def main(): # (8) print("running main()") print("registry ->", registry) f1() f2() f3() if __name__ == "__main__": main() # (9) |
1. В registry хранятся ссылки на функции, декорированные @register.
2. register принимает функцию в качестве аргумента.
3. Показываем, какая функция декорируется – для демонстрации.
4. Включаем func в registry.
5. Возвращаем func: мы должны вернуть функцию, в данном случае возвращается та же функция, что была передана на входе.
6. f1 и f2 декорированы @register.
7. f3 не декорирована.
8. main распечатывает registry, затем вызывает f1(), f2() и f3().
9. main() вызывается только тогда, когда registration.py запускается как скрипт.
Будучи запущена как скрипт, программа registration.py выводит следующие строки:
1 2 3 4 5 6 7 8 9 |
admin@pythonlearn.ru:~$ python3 registration.py running register(<function f1 at 0x7f69ee2a07b8>) running register(<function f2 at 0x7f69ee2a0840>) running main() registry -> [<function f1 at 0x7f69ee2a07b8>, <function f2 at 0x7f69ee2a0840>] running f1() running f2() running f3() admin@pythonlearn.ru:~$ |
Отметим, что register выполняется дважды до любой другой функции в модуле. При вызове register получает в качестве аргумента декорируемый объект-функцию, например <function f1 at 0x7f69ee2a07b8>.
После загрузки модуля в register оказываются ссылки на две декорированные функции: f1 и f2. Они, как и функция f3, выполняются только при явном вызове из main.
Если registration.py импортируется а не запускается как скрипт, то вывод выглядит так:
1 2 3 4 |
>>> import registration running register(<function f1 at 0x7f5893ccebf8>) running register(<function f2 at 0x7f5893ccec80>) >>> |
Если сейчас заглянуть в registry, то мы увидим:
1 2 3 |
>>> registration.registry [<function f1 at 0x7f5893ccebf8>, <function f2 at 0x7f5893ccec80>] >>> |
Основная цель примера №1 – подчеркнуть, что декораторы функций выполняются сразу после импорта модуля, но сами декорируемые функции – только в результате явного вызова.
В этом проявляется различие между этапом импорта и этапом выполнения в Python.
Планирую внедрять промо-ролики-уроки Python с помощью Adobe After Effects. Сейчас много таких готовых роликов можно скачать на Hunterae.com. Например, можете взглянуть на проект Code Source.
По сравнению с типичным применением декораторов в реальных программах пример №1 необычен в двух отношениях:
- Функция декоратор определена в том же модуле, что и декорируемые функции. Настоящий декоратор обычно определяется в одном модуле и применяется к функциям из других модулей.
- Декоратор register возвращает ту же функцию, что была передана в качестве аргумента. На практике декоратор обычно определяет внутреннюю функцию и возвращает именно ее.
Хотя декоратор register из примера №1 возвращает декорированную функцию без изменения, эта техника не бесполезна.
Сайт https://pricesmm.com/ проработал тему «Накрутка ботов в Инстаграме дёшево». Выявлены существенные различия в способах и методах и довольно широкий разброс цен. Узнайте, как накрутить ботов в Instagram максимально эффективно и выгодно.
Подобные декораторы используются во многих веб-фреймворков, написанных на Python, например Django и Flask, с целью добавления функций в некий центральный реестр, например, для отображения образцов URL на функции, генерирующие HTTP-ответы.
Такие регистрационные декораторы могут изменять декорируемую функцию, но это необязательно.