В мире программирования повышение функциональности кода без изменения его структуры — это навык, который стоит освоить. В Python одной из технологий, позволяющих достичь этой цели, является использование декораторов. Декораторы помогают «дополнять» нашу функцию, не внося в неё изменений, а оборачивая её в дополнительную логику.
Дополнение возможностей нашей функции, не изменяя её внутренности (не переписывая код) возможно с помощью декораторов.
Декораторы — это мощный инструмент, который позволяет изменять поведение функции или метода, не касаясь их внутреннего кода. В этом блоге мы разберемся, как они работают, и создадим свой собственный декоратор. Дополнительно, мы дадим советы по улучшению кода с декораторами, рассмотрим плюсы и минусы их использования и объясним, почему декораторы считаются столь важными в Python.
Декоратор можно применять к любой функции, изменяя её функционал и не переписывая ни строчки кода.
Декораторы: дополнение без изменения
Основная идея декоратора заключается в том, чтобы взять функцию, обернуть её в дополнительную функциональность и вернуть уже изменённую версию обратно. Как только функция обернута декоратором, её поведение будет дополнено или вовсе изменено, без изменения строк её исходного кода.
С помощью функции декоратор мы декорируем передаваемую функцию, то есть изменяем её поведение.
Декоратор, как бы оборачивает исходную функцию в любой код, который нам потребуется.
Создание декоратора: стадия за стадией
Для создания декоратора, нам потребуется:
1. Функция-декоратор: Она принимает другую функцию в качестве аргумента.
def decorator(func):
2. Вложенная функция-обёртка: Эта функция будет выполнять дополнительное поведение.
def wrapped_func(*args, **kwargs):
Вложенная функция, обычно, называется wrapped или wrapped_func.
В скобках мы передаём *args и **kwargs, что бы можно было обернуть любую функцию и с любым количеством параметров.
Благодаря использованию параметров *args и **kwargs, мы можем обернуть функцию с любым количеством аргументов.
wrapped переводится, как обёртка.
wrapped_func переводится, как обёрнутая функция.
3. Код обертки: Здесь может происходить любая логика, которую вы хотите обернуть вокруг основной функции.
print("До вызова функции")
value = func(*args, **kwargs)
print("После вызова функции")
В этой части часто происходит логирование, авторизация или изменение аргументов.
В коде обёртки может происходить что угодно, как до вызова func, так и после него.
4. Возврат функции-обёртки: Она возвращает результат исполнения и становится новой функциональной версией исходной функции.
return wrapped_func
В конце декоратор возвращает функцию-обёртку в качестве объекта, то есть без скобок: return wrapped_func. При этом обёртка возвращает результат выполнения func.
Вот полный пример с расшифровкой каждой строки кода:
Тот же код ниже для копирования и вставки в программу. Не забывайте про необходимый отступ пробелами в определённых местах в начале строки, так как код на сервере блога может отображаться некорректно.
def decorator(func):
def wrapped_func(*args, **kwargs): # Вложенная функция, принимающая любые аргументы
print("До вызова функции") # Дополнительный код перед вызовом основной функции
value = func(*args, **kwargs) # Вызов основной функции
print("После вызова функции") # Дополнительный код после выполнения функции
return value # Возврат результата выполнения основной функции
return wrapped_func # Декоратор возвращает обернутую функцию
Применение декоратора
Чтобы использовать декоратор, достаточно добавить его перед функцией с помощью символа @ (собака):
При вызове my_function(), вы получите:
До вызова функции
Основная функция
После вызова функции
При вызове функции для создания её задекорированной версии достаточно записать @декоратор. Этот приём оборачивает код функции в декоратор. И теперь мы можем использовать нашу функцию как обычно и без переприсваивания значений.
Полный код на основании разобранного материала выше:
Тот же код ниже для копирования и вставки в программу. Не забывайте про необходимый отступ пробелами в определённых местах в начале строки, так как код на сервере блога может отображаться некорректно.
def decorator(func):
def wrapped_func(*args, **kwargs): # Вложенная функция, принимающая любые аргументы
print("До вызова функции") # Дополнительный код перед вызовом основной функции
value = func(*args, **kwargs) # Вызов основной функции
print("После вызова функции") # Дополнительный код после выполнения функции
return value # Возврат результата выполнения основной функции
return wrapped_func # Декоратор возвращает обернутую функцию
@decorator
def my_function():
print("Основная функция")
my_function()
Результат работы кода:
Декоратор является одним из шаблонов проектирования в программировании, наряду с итераторами, которым пользуются довольно часто.
Рекомендации по улучшению кода
- Именование: Давайте вашим декораторам говорящие имена, отражающие их назначение.
- Множество декораторов: Вы можете «обернуть» функцию в несколько декораторов одновременно, просто указав их в ряд.
- Документация: Используйте functools.wraps для сохранения метаданных об исходной функции в обёртке.
- Тестирование и отладка: Расширяйте ваши тестовые сценарии, чтобы гарантировать корректную работу обёрток.
Плюсы и минусы декораторов
Плюсы:
- Удобство добавления функциональности.
- Модульность и повторное использование кода.
Минусы:
- Отладка сложна, необходимы расширенные навыки работы с инструментами отладки.
Заключение
Декораторы — это неотъемлемая часть Python, популярная среди разработчиков благодаря своему удобному интерфейсу и широким возможностям. Если вы научитесь применять их эффективно, то сможете существенно улучшить архитектуру своих программ. Они помогут создавать более чистый и модульный код и ускорят процесс разработки. Применяйте декораторы с умом, и они станут вашим незаменимым инструментом в мире Python.
Полезные ресурсы:
---------------------------------------------------
Сообщество дизайнеров в VK
https://vk.com/grafantonkozlov
Телеграмм канал сообщества
https://t.me/grafantonkozlov
Архив эксклюзивного контента
https://boosty.to/antonkzv
Канал на Дзен
https://dzen.ru/grafantonkozlov
---------------------------------------------------
Бесплатный Хостинг и доменное имя
https://tilda.cc/?r=4159746
Мощная и надежная нейронная сеть Gerwin AI
https://t.me/GerwinPromoBot?start=referrer_3CKSERJX
GPTs — плагины и ассистенты для ChatGPT на русском языке
https://gptunnel.ru/?ref=Anton
---------------------------------------------------
Донат для автора блога