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

Можно ли задекорировать класс?

2.0 Middle🔥 161 комментариев
#Python Core

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

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

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

# Да, класс можно задекорировать

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

Базовый пример декоратора класса

def add_debug_info(cls):
    """Декоратор добавляет __debug_info в класс"""
    cls.__debug_info = f"Class {cls.__name__}"
    return cls

@add_debug_info
class MyClass:
    pass

print(MyClass.__debug_info)  # Class MyClass

Практический пример: singleton

def singleton(cls):
    """Гарантирует один инстанс класса"""
    instances = {}
    
    def get_instance(*args, **kwargs):
        if cls not in instances:
            instances[cls] = cls(*args, **kwargs)
        return instances[cls]
    
    return get_instance

@singleton
class Database:
    def __init__(self, url):
        self.url = url

db1 = Database("postgres://localhost")
db2 = Database("different_url")
print(db1 is db2)  # True, один и тот же объект

Добавление методов через декоратор

def add_repr(cls):
    """Автоматически добавляет __repr__"""
    def __repr__(self):
        attrs = ', '.join(f"{k}={v!r}" for k, v in self.__dict__.items())
        return f"{cls.__name__}({attrs})"
    
    cls.__repr__ = __repr__
    return cls

@add_repr
class Point:
    def __init__(self, x, y):
        self.x = x
        self.y = y

p = Point(3, 4)
print(p)  # Point(x=3, y=4)

Декоратор с параметрами

def validate_attributes(required_attrs):
    """Проверяет наличие required атрибутов в классе"""
    def decorator(cls):
        for attr in required_attrs:
            if not hasattr(cls, attr):
                raise TypeError(f"Класс {cls.__name__} должен иметь атрибут {attr}")
        return cls
    return decorator

@validate_attributes(["REQUIRED_VALUE"])
class ConfigClass:
    REQUIRED_VALUE = 10

Functools.wraps для метаданных

import functools

def preserve_metadata(cls):
    """Сохраняет метаданные класса"""
    cls.__wrapped__ = cls
    return cls

@preserve_metadata
class MyService:
    """Мой сервис"""
    pass

Использование в стандартной библиотеке

Стандартные примеры из Python:

  • @dataclass — автоматически генерирует init, repr, eq
  • @functools.lru_cache — кеширование для методов класса
  • @property — превращает метод в свойство

Важные нюансы

  1. Порядок применения — декораторы применяются снизу вверх
  2. Сигнатура — декоратор класса должен принять класс и вернуть класс (или callable)
  3. Вернуть можно не только класс — можно вернуть функцию, которая создаёт инстансы
  4. Наследование — декорированные классы можно наследовать, но декоратор применится только к подклассу при его определении

Когда использовать

  • Добавление функционала ко всем методам класса
  • Реализация паттернов (singleton, factory, proxy)
  • Валидация структуры класса
  • Регистрация классов в реестре
  • Логирование создания экземпляров

Декораторы классов — мощный инструмент для метапрограммирования и DRY-кода.

Можно ли задекорировать класс? | PrepBro