
Власти России поставили точку в вопросе YouTube и Роскомнадзора
17-04-2025, 20:53
Авторизуйтесь или зарегистрируйтесь, чтобы оценивать материалы, создавать записи и писать комментарии.
АвторизоватьсяДекораторы в Python нужны, чтобы добавлять новое поведение к функциям или классам без изменения их кода. Они позволяют решать различные задачи, например:
- Логирование. Замер времени работы функции или программы.
- Кэширование. Если при работе функции образуются промежуточные результаты и нужно запомнить их все.
- Ограничение скорости. Если нужно замедлить работу какой-то функции.
- Повторное выполнение. Если нужно, чтобы какая-то функция отработала два или больше раз.
- Контроль доступа. Если нужно проверить, что пользователь авторизован.
decorators.py – Полный код с примерами:
import functools
import time
from typing import Callable, Any
import random
# ===== 1. Декоратор кэширования с таймером =====
def cached_with_ttl(ttl_seconds: int = 60):
"""Кэширует результат функции на указанное время (TTL)."""
def decorator(func: Callable) -> Callable:
cache = {}
@functools.wraps(func)
def wrapper(*args, **kwargs) -> Any:
cache_key = (args, frozenset(kwargs.items()))
if cache_key in cache:
cached_time, result = cache[cache_key]
if (time.time() - cached_time) < ttl_seconds:
print(f"Используем кэш для {func.__name__}!")
return result
result = func(*args, **kwargs)
cache[cache_key] = (time.time(), result)
return result
return wrapper
return decorator
# Пример использования:
@cached_with_ttl(ttl_seconds=10)
def expensive_calculation(x: int) -> int:
print("Вычисляю... Это долго!")
time.sleep(2)
return x * x
# Тест:
print(expensive_calculation(5)) # Первый вызов – вычисляет
print(expensive_calculation(5)) # Второй вызов (менее 10 сек) – берёт из кэша
# ===== 2. Декоратор валидации аргументов =====
def validate_args(*validators: Callable):
"""Проверяет аргументы функции перед выполнением."""
def decorator(func: Callable) -> Callable:
@functools.wraps(func)
def wrapper(*args, **kwargs) -> Any:
for i, (arg, validator) in enumerate(zip(args, validators)):
if not validator(arg):
raise ValueError(f"Аргумент {i} ({arg}) не прошёл валидацию!")
return func(*args, **kwargs)
return wrapper
return decorator
# Пример использования:
@validate_args(lambda x: x > 0, lambda y: isinstance(y, str))
def divide_and_print(x: int, text: str) -> str:
return f"{text}: {1 / x}"
print(divide_and_print(2, "Hello")) # Ok
# print(divide_and_print(0, "Hello")) # ValueError: Аргумент 0 (0) не прошёл валидацию!
# ===== 3. Декоратор для логирования SQL-запросов (имитация) =====
def log_sql_queries(verbose: bool = True):
"""Логирует 'SQL-запросы' (имитация для ORM)."""
def decorator(func: Callable) -> Callable:
@functools.wraps(func)
def wrapper(*args, **kwargs) -> Any:
if verbose:
print(f"[SQL] Запрос: {func.__name__} с args={args}, kwargs={kwargs}")
result = func(*args, **kwargs)
if verbose:
print(f"[SQL] Результат: {result}")
return result
return wrapper
return decorator
# Пример использования:
@log_sql_queries()
def get_user(user_id: int) -> dict:
# Имитация запроса к БД
return {"id": user_id, "name": "Alice"}
get_user(1) # Выведет логи в консоль
# ===== 4. Декоратор контроля памяти =====
def measure_memory(func: Callable) -> Callable:
"""Замеряет потребление памяти функцией (упрощённо)."""
@functools.wraps(func)
def wrapper(*args, **kwargs) -> Any:
import tracemalloc
tracemalloc.start()
result = func(*args, **kwargs)
snapshot = tracemalloc.take_snapshot()
tracemalloc.stop()
top_stats = snapshot.statistics('lineno')
print(f"[Memory] Пиковое использование: {top_stats[0].size / 1024:.2f} KB")
return result
return wrapper
# Пример использования:
@measure_memory
def create_large_list(n: int) -> list:
return [random.random() for _ in range(n)]
create_large_list(100_000) # Выведет данные о памяти
Пример вывода в консоли:
17-04-2025, 20:53
19-04-2025, 15:06
21-04-2025, 02:51
Комментариев нет