""" Урок 65. Практикум 16 — весь код примеров одним файлом. Источник: subjects/python-fundamentals/course/lessons/65-practice-16/examples.html Файл собран автоматически (tools/build_lesson_examples.py): правьте страницу урока. Запуск: python lesson-65.py """ # ==================================================================== # Пример 1. Обрезка строки # ==================================================================== def limit_output(func): max_len = 20 def wrapper() -> str: result = func() if len(result) <= max_len: return result return result[:max_len - 3] + "..." return wrapper @limit_output def get_text() -> str: return "Это очень длинный текст, который нужно обрезать." print(get_text()) # Это очень длинный... # ==================================================================== # Пример 2. Параметризованная обрезка # ==================================================================== def limit_output(max_len: int): def decorator(func): def wrapper() -> str: result = func() if len(result) <= max_len: return result return result[:max_len - 3] + "..." return wrapper return decorator @limit_output(26) def get_text() -> str: return "Это очень длинный текст, который нужно обрезать." print(get_text()) # Это очень длинный текст... # ==================================================================== # Пример 3. Простое кэширование # ==================================================================== def cache(func): memo: dict[tuple, int] = {} def wrapper(*args): if args not in memo: memo[args] = func(*args) else: print("Результат из кеша: ") return memo[args] return wrapper @cache def multiply(a: int, b: int) -> int: print(f"Вычисляем {a} * {b}: ") return a * b print(multiply(2, 3)) print(multiply(2, 3)) print(multiply(4, 5)) print(multiply(2, 3)) # ==================================================================== # Пример 4. Кэш с ограничением размера # ==================================================================== from collections import OrderedDict def cache(max_size: int = 5): def decorator(func): memo: OrderedDict[tuple, int] = OrderedDict() def wrapper(*args): if args in memo: print("Результат из кеша: ") memo.move_to_end(args) else: result = func(*args) if len(memo) >= max_size: memo.popitem(last=False) memo[args] = result return memo[args] return wrapper return decorator @cache(max_size=2) def multiply(a: int, b: int) -> int: print(f"Вычисляем {a} * {b}: ") return a * b print(multiply(2, 3)) print(multiply(2, 3)) print(multiply(4, 5)) print(multiply(6, 7)) print(multiply(2, 3)) # будет пересчитан # ==================================================================== # Пример 5. Логирование в файл # ==================================================================== import logging logging.basicConfig( filename="call_log.log", level=logging.INFO, format="%(message)s", encoding="utf-8", ) def log_to_file(func): def wrapper(*args, **kwargs): result = func(*args, **kwargs) all_args = ", ".join(str(arg) for arg in args) all_kwargs = ", ".join(f"{k}={v!r}" for k, v in kwargs.items()) logging.info( f"function: {func.__name__} | " f"args: {all_args if all_args else None}; " f"kwargs: {all_kwargs if all_kwargs else None} | " f"return: {result}" ) return result return wrapper @log_to_file def add(a: int, b: int) -> int: return a + b @log_to_file def greet_with_name(name: str, punctuation: str = "!") -> str: return f"Hello, {name}{punctuation}" @log_to_file def greet() -> str: return "Hello" add(5, 3) greet_with_name("Alice", punctuation=".") greet() # ==================================================================== # Пример 6. Проверка типов # ==================================================================== def accepts_types(*expected_types): def decorator(func): def wrapper(*args): for arg, expected in zip(args, expected_types): if not isinstance(arg, expected): raise TypeError( f"Incorrect type for argument '{arg}': " f"expected - {expected}, received - {type(arg)}" ) return func(*args) return wrapper return decorator @accepts_types(int, int) def add(a: int, b: int) -> int: return a + b @accepts_types(str) def greet(name: str) -> str: return f"Hello, {name}!" @accepts_types(str, str) def greet_by_name(name: str, punctuation: str = "!") -> str: return f"Hello, {name}{punctuation}" try: print(add(5, 3)) print(greet_by_name("Anna")) print(greet_by_name("Anna", 0)) except Exception as e: print(e)