Короткий ответ
Декоратор — функция, принимающая другую функцию и возвращающая новую функцию (обычно wrapper), которая добавляет поведение до/после вызова оригинала без изменения его кода.
Как это работает подробнее
Синтаксис @decorator над определением функции эквивалентен func = decorator(func) — декоратор получает исходную функцию, внутри определяет wrapper, вызывающий оригинал и добавляющий логику, и возвращает wrapper вместо исходной функции.
Пример кода
example-245.py
import functools
def log_calls(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
print(f"Вызов {func.__name__} с args={args}, kwargs={kwargs}")
result = func(*args, **kwargs)
print(f"Результат: {result}")
return result
return wrapper
@log_calls
def add(a, b):
return a + b
add(2, 3) # в логе видны аргументы (2, 3) и результат 5Что использовать на практике
- Практика. Декораторы удобны для сквозной функциональности: логирования, замера времени, проверки прав доступа, кэширования — без дублирования кода в каждой функции.
wrapperдолжен пробрасывать аргументы через*args, kwargs, чтобы не ограничивать сигнатуру оригинала.
Подводные камни
- Риски. Забывают вернуть результат вызова оригинальной функции из
wrapper(функция тогда всегда возвращаетNone); не пробрасывают*args/kwargs, из-за чего декорированная функция перестаёт принимать аргументы, которые принимала исходная.