Ответ
Да, постоянно. Декораторы — это мощный паттерн в Python для модификации или расширения поведения функций и классов без изменения их исходного кода. Я использую как встроенные декораторы из стандартной библиотеки, так и пишу собственные для решения конкретных задач.
Практические примеры из моего опыта:
-
Логирование и профилирование:
import time import functools from typing import Callable def log_execution_time(func: Callable) -> Callable: """Декоратор для логирования времени выполнения функции.""" @functools.wraps(func) # Важно: сохраняет метаданные оригинальной функции def wrapper(*args, **kwargs): start = time.perf_counter() result = func(*args, **kwargs) end = time.perf_counter() print(f"[LOG] {func.__name__} executed in {end - start:.4f} seconds") return result return wrapper @log_execution_time def process_large_dataset(data: list): """Имитация долгой обработки.""" time.sleep(0.5) return sum(data) # Использование process_large_dataset([1, 2, 3, 4, 5]) # Вывод: [LOG] process_large_dataset executed in 0.5001 seconds -
Кеширование результатов тяжелых вычислений (используя
@functools.lru_cache):from functools import lru_cache @lru_cache(maxsize=128) # Кеширует до 128 уникальных вызовов def fibonacci(n: int) -> int: """Рекурсивное вычисление числа Фибоначчи с мемоизацией.""" if n < 2: return n return fibonacci(n-1) + fibonacci(n-2) # Без @lru_cache вызов fibonacci(35) был бы крайне медленным. # С декоратором результат для каждого 'n' вычисляется один раз. print(fibonacci(35)) # Быстро -
Валидация аргументов и проверка прав доступа в веб-приложении (на примере Flask-like подхода):
def require_auth(role: str = "user"): """Декоратор для проверки авторизации и роли пользователя.""" def decorator(func): @functools.wraps(func) def wrapper(*args, **kwargs): # Здесь была бы реальная проверка токена или сессии current_user = get_current_user_from_request() if not current_user or current_user.role != role: raise PermissionError(f"Access denied. Required role: {role}") return func(*args, **kwargs) return wrapper return decorator @require_auth(role="admin") def delete_user(user_id: int): """Только администратор может удалять пользователей.""" # ... логика удаления ... return f"User {user_id} deleted" -
Регистрация обработчиков (паттерн Plugin):
_PROCESSORS = {} def register_processor(name: str): """Декоратор для регистрации функций-обработчиков в словаре.""" def decorator(func): _PROCESSORS[name] = func return func return decorator @register_processor("json") def parse_json(data: str): import json return json.loads(data) @register_processor("csv") def parse_csv(data: str): import csv # ... парсинг CSV ... return rows # Теперь можно динамически выбирать обработчик def process(data: str, format_type: str): processor = _PROCESSORS.get(format_type) if processor: return processor(data) raise ValueError(f"Unsupported format: {format_type}")
Ключевое преимущество декораторов — они позволяют отделить сквозную функциональность (cross-cutting concerns), такую как логирование, кеширование, безопасность, от основной бизнес-логики, делая код чище и более поддерживаемым.