Ответ
Декоратор в Python — это функция, которая принимает другую функцию в качестве аргумента, расширяет её поведение и возвращает новую, обёрнутую функцию. Это мощный паттерн для добавления сквозной функциональности (например, логирование, кеширование, проверка прав) без изменения исходного кода целевой функции.
Пример простого декоратора для логирования:
def logger(func):
def wrapper(*args, **kwargs):
print(f'Вызов функции {func.__name__} с аргументами: {args}, {kwargs}')
result = func(*args, **kwargs)
print(f'Функция {func.__name__} вернула: {result}')
return result
return wrapper
@logger
def add(a, b):
return a + b
# Вызов обёрнутой функции
add(5, 3)
# Вывод:
# Вызов функции add с аргументами: (5, 3), {}
# Функция add вернула: 8
Синтаксис @decorator — это просто «синтаксический сахар» для add = logger(add). Для сохранения метаданных исходной функции (например, __name__) рекомендуется использовать functools.wraps.
Ответ 18+ 🔞
А, декораторы в Python! Ну это ж, ёпта, просто золотая жила для ленивых, но хитрых программистов. Представь себе: есть у тебя функция, которая делает своё дело, а ты такой — «хочу, чтобы она ещё и логировала каждый свой чих, но лезть внутрь и ковырять её код — терпения ноль, ебать».
Вот тут-то декоратор и выручает, как верный друг. По сути, это такая функция-обёртка, которая хватает твою родную функцию за жопу, наряжает её в дополнительные действия и отдаёт тебе обратно уже новую, улучшенную версию. Всё это без единого правка в оригинале! Красота же, блядь.
Смотри, вот тебе классический пример — декоратор для логирования. Чистая магия, хуй с горы.
def logger(func):
def wrapper(*args, **kwargs):
print(f'Вызов функции {func.__name__} с аргументами: {args}, {kwargs}')
result = func(*args, **kwargs)
print(f'Функция {func.__name__} вернула: {result}')
return result
return wrapper
@logger
def add(a, b):
return a + b
# Вызов обёрнутой функции
add(5, 3)
# Вывод:
# Вызов функции add с аргументами: (5, 3), {}
# Функция add вернула: 8
Видишь эту собачку @logger над функцией add? Это и есть тот самый волшебный пинок. Всё, что она делает — это подменяет твою старую add на новую, которую вернул logger. По-честному, это то же самое, что написать add = logger(add). Просто так, с собачкой, выглядит как будто ты накинул на функцию плащ-невидимку с суперспособностями.
А теперь главный подвох, из-за которого все начинающие охуевают. После такой подмены у твоей функции add меняется имя! Она теперь будет зваться не add, а wrapper, потому что именно эту внутреннюю функцию мы и вернули. Это, конечно, пиздец как неудобно, когда что-то ломается и в логах ты видишь кучу одинаковых wrapper.
Чтобы не было такого конфуза, умные дядьки придумали functools.wraps. Эта штука как раз копирует все метаданные оригинальной функции (имя, документацию и прочее) в нашу обёртку. Без неё — ты распиздяй, с ней — молодец.
Короче, декораторы — это овердохуища мощный инструмент. Хочешь кешировать результаты, проверять авторизацию, замерять время выполнения — вешай декоратор и не парься. Главное — понять эту идею обёртки, а дальше уже можно творить, что душе угодно.