Короткий ответ
Декоратор — способ изменить или расширить поведение функции, метода или класса без изменения их исходного кода. По сути это функция, которая принимает другую функцию и возвращает новую функцию с расширенной функциональностью.
Как это работает подробнее
- Синтаксический сахар. Запись
@decoratorперед определением эквивалентна строкеfunc = decorator(func)после него. - Обёртка. Внутри декоратора обычно определяется функция
wrapper, которая выполняет дополнительные действия и затем вызывает исходную функцию. - Применение. Декораторы используют для логирования, проверки прав, кэширования, валидации аргументов и подобных сквозных задач.
- Переиспользование. Общая логика выносится из тела функций в декоратор и применяется в чистом виде к разным функциям.
Пример кода
Простейший декоратор с логированием вызовов
def decorator(func):
def wrapper():
print('До вызова функции')
func()
print('После вызова функции')
return wrapper
@decorator
def hello():
print('Hello!')
hello() # равносильно hello = decorator(hello)Что использовать на практике
- Сквозная логика. Выноси в декоратор повторяющиеся действия — логирование, замер времени, контроль доступа.
- Переиспользование. Часто нужные обёртки оформляй в отдельном модуле и применяй к разным функциям.
- Метаданные. Внутри обёртки используй
functools.wraps, чтобы не терять имя и документацию исходной функции.
Подводные камни
- Потеря метаданных. Без
@wrapsу декорированной функции меняются__name__и__doc__, что мешает отладке и интроспекции.