Найти в Дзене

Декоратор в Python

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

Декоратор - это функция, которая принимает другую функцию в качестве входных данных и возвращает новую функцию.

🎯 Простой декоратор

Сначала определите декоратор, затем примените его с помощью `@имя_декоратора` над функцией.

-2

Размещая @changecase непосредственно над определением функции, функция myfunction "декорируется" функцией changecase.

🔄 Множественные вызовы декоратора

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

Пример
Использование декоратора @changecase на двух функциях:

-3

📝 Аргументы в декорируемой функции

Функции, требующие аргументы, также могут быть декорированы - просто убедитесь, что передаёте аргументы в функцию-обёртку:

Пример
Декорирование функций с аргументами:

-4

🌟 *args и **kwargs

Иногда декоратор не контролирует аргументы, передаваемые из декорируемой функции. Чтобы решить эту проблему, добавьте (*args, **kwargs) в функцию-обёртку - так она сможет принимать любое количество аргументов любого типа и передавать их в декорируемую функцию.

Пример
Защита функции с аргументами *args и **kwargs:

-5

🎁 Декоратор с аргументами

Декораторы могут принимать собственные аргументы, добавляя ещё один уровень обёртки.

Пример
Фабрика декораторов, которая принимает аргумент и преобразует регистр на основе значения аргумента:

-6

🎪 Множественные декораторы

Вы можете использовать несколько декораторов на одной функции.

Это делается путём размещения вызовов декораторов друг над другом.

Декораторы вызываются в обратном порядке от их указания.

Пример
Один декоратор для верхнего регистра и один для добавления приветствия:

-7

Этот декоратор автоматически запоминает результаты вычислений, что особенно полезно для ресурсоёмких функций! 🎯

🛡️ Сохранение метаданных функции

Функции в Python содержат метаданные, к которым можно обратиться с помощью атрибутов `__name__` и `__doc__`.

Пример

Обычно имя функции можно получить с помощью атрибута `__name__`:

-8

Но когда функция декорируется, метаданные оригинальной функции теряются. 😱

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

-9

Чтобы исправить это, в Python есть встроенная функция functools.wraps, которую можно использовать для сохранения оригинального имени функции и строки документации. 🎯

Пример
Импортируйте functools.wraps для сохранения оригинального имени функции и строки документации:

-10

💡 Всегда используйте functools.wraps!

Это считается best practice при создании декораторов. Вот почему это важно:

Без @functools.wraps вы бы потеряли всю эту ценную информацию! 🎭✨

Ключевые преимущества использования `functools.wraps`:**

✅ Сохраняет оригинальное имя функции

✅ Сохраняет строку документации (`__doc__`)

✅ Сохраняет другие метаданные (модуль, квалифицированное имя и т.д.)

✅ Делает отладку значительно проще

✅ Считается best practice в Python сообществе