← Назад к вопросам

Мог ли показать свой код за который не стыдно

1.3 Junior🔥 201 комментариев
#Другое

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI28 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Декораторы в Python: мощный инструмент метапрограммирования

Декораторы — это один из самых элегантных и мощных механизмов Python. За мои 10+ лет разработки я использовал их в десятках проектов для улучшения качества кода и добавления функциональности.

Что такое декоратор

Декоратор — это функция, которая принимает другую функцию в качестве аргумента и возвращает новую функцию с дополнительной функциональностью. Это позволяет обернуть функцию без изменения её исходного кода.

# Простейший пример декоратора
def my_decorator(func):
    def wrapper(*args, **kwargs):
        print(f"Вызываю {func.__name__}")
        result = func(*args, **kwargs)
        print(f"Завершён {func.__name__}")
        return result
    return wrapper

@my_decorator
def hello(name):
    print(f"Привет, {name}!")

hello("Мир")
# Output:
# Вызываю hello
# Привет, Мир!
# Завершён hello

Практические примеры декораторов

Логирование и мониторинг

import logging
import time
from functools import wraps

def timing_logger(func):
    @wraps(func)  # Сохраняет метаинформацию оригинальной функции
    def wrapper(*args, **kwargs):
        start = time.time()
        try:
            result = func(*args, **kwargs)
            logging.info(f"{func.__name__} выполнена за {time.time() - start:.2f}s")
            return result
        except Exception as e:
            logging.error(f"{func.__name__} ошибка: {e}", exc_info=True)
            raise
    return wrapper

@timing_logger
def process_data(items):
    time.sleep(1)  # Долгая операция
    return len(items)

Валидация аргументов

from typing import Callable

def validate_positive(*param_names):
    def decorator(func):
        @wraps(func)
        def wrapper(*args, **kwargs):
            # Проверяем, что аргументы положительные
            for param in param_names:
                if param in kwargs and kwargs[param] < 0:
                    raise ValueError(f"{param} должен быть положительным")
            return func(*args, **kwargs)
        return wrapper
    return decorator

@validate_positive('amount', 'rate')
def calculate_interest(amount, rate):
    return amount * rate / 100

calculate_interest(amount=100, rate=-5)  # Raises ValueError

Кеширование результатов (Memoization)

from functools import lru_cache

@lru_cache(maxsize=128)
def expensive_computation(n):
    # Результаты будут кешированы
    return sum(i**2 for i in range(n))

# Первый вызов: вычисляет
expensive_computation(10000)

# Второй вызов: берёт из кеша
expensive_computation(10000)  # Мгновенно!

Управление доступом (Permissions)

from functools import wraps
from flask import request, jsonify

def require_role(role):
    def decorator(func):
        @wraps(func)
        def wrapper(*args, **kwargs):
            user_role = request.headers.get('X-User-Role')
            if user_role != role:
                return jsonify({"error": "Access denied"}), 403
            return func(*args, **kwargs)
        return wrapper
    return decorator

@require_role('admin')
def delete_user(user_id):
    # Только admins могут удалять пользователей
    return {"status": "deleted"}

Асинхронные операции (Async/Await)

import asyncio
from functools import wraps

def async_timeout(seconds=5):
    def decorator(func):
        @wraps(func)
        async def wrapper(*args, **kwargs):
            try:
                return await asyncio.wait_for(
                    func(*args, **kwargs),
                    timeout=seconds
                )
            except asyncio.TimeoutError:
                raise Exception(f"Function timed out after {seconds}s")
        return wrapper
    return decorator

@async_timeout(seconds=3)
async def fetch_data(url):
    # Будет отменена, если выполняется дольше 3 секунд
    result = await some_http_request(url)
    return result

Декораторы классов

Singleton паттерн

def singleton(cls):
    instances = {}
    
    @wraps(cls)
    def get_instance(*args, **kwargs):
        if cls not in instances:
            instances[cls] = cls(*args, **kwargs)
        return instances[cls]
    
    return get_instance

@singleton
class DatabaseConnection:
    def __init__(self, connection_string):
        self.connection_string = connection_string

# Всегда возвращает один и тот же объект
db1 = DatabaseConnection("postgres://...")
db2 = DatabaseConnection("postgres://...")
assert db1 is db2  # True!

Dataclass с валидацией

from dataclasses import dataclass, field

def validated_dataclass(cls):
    """Добавляет валидацию к dataclass"""
    @wraps(cls.__init__)
    def new_init(self, **kwargs):
        # Валидируем перед инициализацией
        for key, value in kwargs.items():
            if not isinstance(value, cls.__annotations__[key]):
                raise TypeError(f"{key} должен быть {cls.__annotations__[key]}")
        cls.__init__(self, **kwargs)
    
    cls.__init__ = new_init
    return cls

Встроенные полезные декораторы Python

class MyClass:
    # property — превращает метод в атрибут
    @property
    def full_name(self):
        return f"{self.first_name} {self.last_name}"
    
    # staticmethod — метод класса без доступа к self
    @staticmethod
    def from_string(data):
        first, last = data.split()
        return MyClass(first, last)
    
    # classmethod — метод класса с доступом к cls
    @classmethod
    def from_dict(cls, data):
        return cls(data['first_name'], data['last_name'])

Когда использовать декораторы

  1. Логирование и мониторинг функций
  2. Валидация входных данных
  3. Кеширование результатов
  4. Контроль доступа (permissions, authentication)
  5. Трансформация результатов функции
  6. Повторные попытки при ошибках (retry logic)
  7. Реалтайм мониторинг performance

Декораторы — это элегантный способ добавить функциональность без изменения исходного кода. Они делают код чище, переиспользуемым и соответствующим принципу DRY.