💻 Практические примеры

⚡ Минимальный рабочий пример

import functools


def greeting_decorator(func):
    @functools.wraps(func)
    def wrapper(*args, **kwargs):
        print("Before")
        result = func(*args, **kwargs)
        print("After")
        return result
    return wrapper


@greeting_decorator
def greet(name: str) -> str:
    return f"Hello, {name}"


print(greet("World"))

Пример 1. Логирование вызовов

import logging
import functools

logging.basicConfig(
    filename="functions.log",
    level=logging.INFO,
    format="%(asctime)s - %(levelname)s - %(message)s",
    encoding="utf-8",
)


def log_decorator(func):
    @functools.wraps(func)
    def wrapper(*args, **kwargs):
        logging.info(f"{func.__name__} called with {args}, {kwargs}")
        result = func(*args, **kwargs)
        logging.info(f"{func.__name__} returned {result}")
        return result
    return wrapper


@log_decorator
def multiply(a: int, b: int) -> int:
    return a * b


print(multiply(4, 5))

Пример 2. Измерение времени выполнения

import time
import functools


def timing_decorator(func):
    @functools.wraps(func)
    def wrapper(*args, **kwargs):
        start = time.perf_counter()
        result = func(*args, **kwargs)
        elapsed = time.perf_counter() - start
        print(f"{func.__name__} took {elapsed:.5f} seconds")
        return result
    return wrapper


@timing_decorator
def slow_function() -> None:
    time.sleep(0.1)
    print("Done")


slow_function()

Пример 3. Автоматический retry

import time
import functools


def retry(attempts: int, delay: float = 1.0):
    def decorator(func):
        @functools.wraps(func)
        def wrapper(*args, **kwargs):
            for attempt in range(1, attempts + 1):
                try:
                    return func(*args, **kwargs)
                except Exception as exc:
                    print(f"Attempt {attempt} failed: {exc}")
                    if attempt < attempts:
                        time.sleep(delay)
            print("All attempts exhausted.")
            return None
        return wrapper
    return decorator


@retry(3, delay=0.5)
def read_file(filename: str) -> str | None:
    with open(filename, "r", encoding="utf-8") as file:
        return file.read()


print(read_file("data.txt"))

Пример 4. Рамка вокруг вывода

import functools


def framed(func):
    @functools.wraps(func)
    def wrapper(*args, **kwargs):
        border = "=" * 40
        print(border)
        result = func(*args, **kwargs)
        print(border)
        return result
    return wrapper


@framed
def show_title() -> None:
    print("== Menu ==")


show_title()

Пример 5. Настраиваемая рамка

import functools


def framed(width: int, symbol: str = "="):
    def decorator(func):
        @functools.wraps(func)
        def wrapper(*args, **kwargs):
            border = symbol * width
            print(border)
            result = func(*args, **kwargs)
            print(border)
            return result
        return wrapper
    return decorator


@framed(30, "-")
def show_title() -> None:
    print("== Menu ==")


show_title()

Пример 6. Среднее время за несколько вызовов

import time
import functools


def measure_time(repeats: int = 5):
    def decorator(func):
        @functools.wraps(func)
        def wrapper(*args, **kwargs):
            total = 0.0
            for _ in range(repeats):
                start = time.perf_counter()
                result = func(*args, **kwargs)
                total += time.perf_counter() - start
            average = total / repeats
            print(f"Average execution time for {repeats} calls: {average:.2f} seconds")
            return result
        return wrapper
    return decorator


@measure_time(5)
def compute() -> int:
    total = 0
    for i in range(1_000_000):
        total += i
    return total


compute()

Как запустить в VS Code

  1. Создайте папку python-fundamentals-practice/lesson-64/.
  2. Создайте файл decorators_examples.py и скопируйте в него примеры.
  3. Откройте терминал в VS Code (Ctrl + `).
  4. Активируйте виртуальное окружение: venv\Scriptsctivate (Windows) или source venv/bin/activate (Mac/Linux).
  5. Запустите: python decorators_examples.py