Объясните концепцию фабрики декораторов и как она применяется в проектировании систем.
Ответ от нейросети
sobes.tech AI
Что хотят услышать интервьюеры:
Фабрика декораторов — это способ параметризовать декоратор и создавать его экземпляры под конкретную задачу. Такой подход позволяет переиспользовать один и тот же механизм обёртки для разных условий, не дублируя код. В проектировании систем это помогает отделять сквозную логику от бизнес-логики и делать поведение функций гибко настраиваемым.
Определение:
Фабрика декораторов — это функция, которая принимает параметры и возвращает декоратор. Сам декоратор уже получает целевую функцию, оборачивает её и добавляет нужное поведение. Идея в том, что сначала задаются настройки, а потом создаётся конкретный декоратор под эти настройки.
Пример использования:
Например, в сервисе нужно логировать выполнение разных операций с разным уровнем детализации. Вместо нескольких почти одинаковых декораторов можно сделать одну фабрику, которая принимает имя события и уровень логирования.
from functools import wraps
def log_event(level):
def decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
print(f"[{level}] Entering {func.__name__}")
result = func(*args, **kwargs)
print(f"[{level}] Leaving {func.__name__}")
return result
return wrapper
return decorator
@log_event("INFO")
def create_user(name):
return f"User {name} created"
@log_event("DEBUG")
def delete_user(user_id):
return f"User {user_id} deleted"
Пояснение кода:
Код показывает три уровня вложенности.
Сначала log_event(level) принимает параметр level и возвращает функцию decorator.
Затем decorator(func) получает исходную функцию и создаёт wrapper, который выполняет дополнительную логику до и после вызова func.
Декоратор @log_event("INFO") сначала вызывает фабрику с аргументом "INFO", а уже результат этой фабрики применяется к create_user.
@wraps(func) сохраняет имя и метаданные исходной функции, что важно для отладки и инструментов, которые используют рефлексию.
Ключевые моменты:
- Фабрика декораторов нужна, когда декоратору требуются параметры.
- Она позволяет не плодить похожие декораторы для разных сценариев.
- Подходит для логирования, метрик, кеширования, проверки прав, троттлинга.
- Упрощает архитектуру: сквозная логика отделяется от бизнес-кода.
@decorator(param)— это обычно вызов фабрики, а не самого декоратора.functools.wrapsжелательно использовать почти всегда, чтобы не терять метаданные функции.