Зарегистрируйтесь для доступа к 15+ бесплатным курсам по программированию с тренажером

Декораторы Python: Функции

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

Давайте реализуем такую функцию, для чего воспользуемся ФВП (функцией высшего порядка):

>>> def printing(function):
...     def inner(*args, **kwargs):
...         result = function(*args, **kwargs)
...         print('result =', result)
...         return result
...     return inner
...
>>> def add_one(x):
...     return x + 1
...
>>> add_one = printing(add_one)
>>> y = add_one(10)
result = 11
>>> y
11

Сначала разберёмся с функцией printing. Эта функция создаёт замыкание inner, которое принимает любые аргументы, применяет к ним функцию, печатает результат и тут же возвращает его. Заметьте, в определении inner я использовал аргументы *args, **kwargs, которые функция без изменения передаёт замкнутой функции function — именно так в Python объявляют "всеядные" функции, которые "пробрасывают" любые комбинации аргументов.

Теперь посмотрим на пример применения printing. В примере я заменил функцию обёрнутым (wrapped) вариантом через присваивание старому имени функции нового значения. Да, функции в Python — обычные переменные в той области видимости, где были объявлены!

Имя "printing" ("печатающий") я выбрал неспроста — подобные обёртки над функциями часто называют в похожей манере. Ведь и по смыслу поведение, которое добавляет обёртка к исходной функции, служит дополнением для этой функции. И читается printing(add_one) практически по-человечески: "добавить единицу, печатая на экран (результат)".

Подобное оборачивание — довольно частая операция в коде, широко использующем функции высшего порядка. Авторы языка Python даже завели для удобного использования функций-обёрток специальный синтаксис! Вот эти самые функции-обёртки вместе с синтаксисом оборачивания называются декораторами.

Тут я вынужден предупредить, что те из вас, кто знаком с паттерном проектирования "Декоратор", могут смело забыть всё, что они знали о нём! Дело в том, что декораторы в Python — сугубо самостоятельная вещь, а не реализации упомянутого паттерна. Те, кому словосочетание "паттерн Декоратор" ничего не говорит, могут не обращать на это замечание внимания :)

Синтаксис применения декоратора

Применения декоратора printing к функции add_one с использованием специального синтаксиса можно записать так:

@printing
def add_one(x):
    return x + 1

Имя декоратора пишется на строчке, предшествующей заголовку функции, а перед именем пишется символ @. После такого применения декоратора нам уже не нужно "переприсваивать" функцию (add_one = printing(add_one))!

Применение даже одного декоратора становится удобнее с таким синтаксисом, но применять подобным образом можно сколько угодно декораторов! Выглядеть это будет так:

@logging
@printing
@cached
def foo():
    # …

Что будет равнозначно коду

foo = cached(foo)
foo = printing(foo)
foo = logging(foo)
# или в одну строку
foo = logging(printing(cached(foo)))

Обратите внимание и запомните: оборачивание происходит сначала в ближайшие к имени функции обёртки, как бы "изнутри наружу" — cached, затем printing и в конце logging.


Аватары экспертов Хекслета

Остались вопросы? Задайте их в разделе «Обсуждение»

Вам ответят команда поддержки Хекслета или другие студенты.

Ошибки, сложный материал, вопросы >
Нашли опечатку или неточность?

Выделите текст, нажмите ctrl + enter и отправьте его нам. В течение нескольких дней мы исправим ошибку или улучшим формулировку.

Что-то не получается или материал кажется сложным?

Загляните в раздел «Обсуждение»:

  • задайте вопрос. Вы быстрее справитесь с трудностями и прокачаете навык постановки правильных вопросов, что пригодится и в учёбе, и в работе программистом;
  • расскажите о своих впечатлениях. Если курс слишком сложный, подробный отзыв поможет нам сделать его лучше;
  • изучите вопросы других учеников и ответы на них. Это база знаний, которой можно и нужно пользоваться.
Об обучении на Хекслете

Для полного доступа к курсу нужна профессиональная подписка

Профессиональная подписка откроет полный доступ ко всем курсам, упражнениям и урокам Хекслета, проектам и пожизненный доступ к теории пройденных уроков. Подписку можно отменить в любой момент.

Получить доступ
900
упражнений
2000+
часов теории
3200
тестов

Открыть доступ

Курсы программирования для новичков и опытных разработчиков. Начните обучение бесплатно.

  • 120 курсов, 2000+ часов теории
  • 900 практических заданий в браузере
  • 360 000 студентов
Отправляя форму, вы соглашаетесь c «Политикой конфиденциальности» и «Условиями оказания услуг»

Наши выпускники работают в компаниях:

Логотип компании Альфа Банк
Логотип компании Aviasales
Логотип компании Yandex
Логотип компании Tinkoff
Рекомендуемые программы

С нуля до разработчика. Возвращаем деньги, если не удалось найти работу.

Иконка программы Python-разработчик
Профессия
Разработка веб-приложений на Django
29 сентября 8 месяцев

Есть вопрос или хотите участвовать в обсуждении?

Зарегистрируйтесь или войдите в свой аккаунт

Отправляя форму, вы соглашаетесь c «Политикой конфиденциальности» и «Условиями оказания услуг»