Ответ
Декоратор в Python — это функция, которая принимает другую функцию и расширяет её поведение без изменения исходного кода. Декораторы оборачивают целевую функцию, добавляя логику до или после её вызова, либо модифицируя её аргументы или результат.
Почему используются: Декораторы позволяют многократно использовать логику (например, логирование, аутентификация, замер времени) для различных функций, сохраняя код чистым и модульным.
Пример простого декоратора:
def my_decorator(func):
def wrapper(*args, **kwargs):
print("До вызова функции")
result = func(*args, **kwargs)
print("После вызова функции")
return result
return wrapper
@my_decorator
def say_hello(name):
print(f"Привет, {name}!")
return f"Hello, {name}"
output = say_hello("Мир")
print(output)
Вывод:
До вызова функции
Привет, Мир!
После вызова функции
Hello, Мир
Ключевые моменты:
- Декоратор принимает функцию как аргумент и возвращает новую функцию (обычно
wrapper). - Синтаксис
@decoratorявляется синтаксическим сахаром дляfunc = decorator(func). - Для сохранения метаданных (имени, docstring) оборачиваемой функции используют
functools.wraps. wrapperдолжен принимать*argsи**kwargs, чтобы оборачиваемая функция могла принимать любые аргументы.
Частые применения:
- Логирование: Запись информации о вызовах функций.
- Замер времени: Измерение времени выполнения функций.
- Кеширование: Сохранение результатов дорогостоящих вычислений.
- Проверка прав доступа: Ограничение доступа к функциям.
- Транзакции БД: Управление транзакциями для функций, работающих с базой данных.
Ответ 18+ 🔞
О, декораторы в питоне, ну это ж классика, блядь! Представь себе такую хуйню: есть у тебя функция, а ты хочешь её обвешать дополнительной логикой, но лезть внутрь и ковырять — лень, да и некрасиво. Вот тут-то декоратор и выручает, сука!
По сути, декоратор — это такая функция-обёртка, которая хватает твою целевую функцию за жопу и говорит: «Стоять, я тебя сейчас улучшу, нахуй!». Она может что-то сделать до вызова, после, или вообще аргументы подменить — полный карт-бланш, ёпта.
Зачем это, спрашивается, нужно? Да чтобы не повторять один и тот же код в каждой функции, блядь! Логирование, замер времени, проверка прав — всё это можно вынести в декоратор и потом просто прилепить сверху, как ярлык «Хрупкое, блядь!».
Смотри, как это выглядит в жизни:
def my_decorator(func):
def wrapper(*args, **kwargs):
print("До вызова функции")
result = func(*args, **kwargs)
print("После вызова функции")
return result
return wrapper
@my_decorator
def say_hello(name):
print(f"Привет, {name}!")
return f"Hello, {name}"
output = say_hello("Мир")
print(output)
А на выходе получаем:
До вызова функции
Привет, Мир!
После вызова функции
Hello, Мир
Важные моменты, чтобы не обосраться:
- Декоратор жрёт функцию и выплёвывает новую, обычно это
wrapper. Всё просто, как три копейки, блядь. - Эта магия с
@— просто синтаксический сахар, чтобы не писатьsay_hello = my_decorator(say_hello). Красиво, ёпта! - Чтобы твоя обёрнутая функция не потеряла имя и докстринг, как последняя мартышлюшка, используй
functools.wraps. Иначе отладка превратится в пиздец. wrapperвсегда должен принимать*args, **kwargs— а то вдруг твоя функция ждёт нестандартный набор аргументов? Не угадаешь, блядь.
Где это применяют? Да везде, сука! Логируют вызовы, замеряют скорость, кешируют результаты (чтобы два раза не считать одно и то же), проверяют, а не шпион ли ты, и управляют транзакциями в базе. В общем, мощнейший инструмент, если руки не из жопы.