Шаг 45.
Python: тонкости программирования.
Эффективные функции. Сила декораторов. Основы декораторов Python

    На этом шаге мы приведем краткое введение в декораторы.

    Итак, что же такое декораторы на самом деле? Они "украшают", или "обертывают", другую функцию и позволяют исполнять программный код до и после того, как обернутая функция выполнится.

    Декораторы позволяют определять конструктивные блоки многократного использования, которые могут изменять или расширять поведение других функций. И они позволяют это делать без необратимых изменений самой обернутой функции. Поведение функции изменяется, только когда оно декорировано.

    Как могла бы выглядеть реализация простого декоратора? В общих чертах декоратор - это вызываемый объект, который на входе принимает один вызываемый объект, а на выходе возвращает другой вызываемый объект.

    Приведенная ниже функция имеет это свойство и может считаться самым простым декоратором, который вы могли когда-либо написать:

>>> def null_decorator(func):
	return func

    Как вы видите, null_decorator() является вызываемым объектом (это функция). На входе он принимает еще один вызываемый объект и на выходе возвращает тот же самый вызываемый объект без его изменения.

    Давайте его применим, чтобы декорировать (или обернуть) еще одну функцию:

>>> def greet():
	return 'Привет!'

>>> greet = null_decorator(greet)
>>> greet()
'Привет!'

    В этом примере мы определили функцию greet() и сразу же ее декорировали, пропустив через функцию null_decorator(). Понимаем, пока это все выглядит бесполезным. Напомним, что мы намеренно спроектировали пустой декоратор бесполезным, верно? Но через мгновение этот пример разъяснит, как работает специальный синтаксис Python, предназначенный для декораторов.

    Вместо того чтобы явным образом вызывать null_decorator() с функцией greet() и затем по-новому присваивать его переменной, удобнее воспользоваться синтаксисом Python @ для декорирования функции:

>>> @null_decorator
def greet():
	return 'Привет!'

>>> greet()
'Привет!'

    Размещение строки @null_decorator перед определением функции аналогично тому, что функция сначала определяется и затем уже прогоняется через декоратор. Синтаксис @ является всего лишь синтаксическим сахаром (syntactic sugar) и краткой формой для этого широко применяемого шаблона.

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

    На следующем шаге мы рассмотрим возможность декораторов менять поведение функции.




Предыдущий шаг Содержание