Как использовать dataclasses для упрощения классов?python-33

Dataclasses (датаклассы) — это декоратор из модуля dataclasses, который автоматически генерирует "магические" методы (__init__, __repr__, __eq__ и др.) для классов, хранящих данные. Они были введены в PEP 557 для уменьшения шаблонного кода.

Основные преимущества

  1. Автоматизация boilerplate-кода (шаблонного кода) — не нужно писать __init__, __repr__ вручную.
  2. Читаемость — структура класса становится декларативной.
  3. Иммутабельность (неизменяемость) — поддержка через параметр frozen=True.

Пример без dataclass:

class Person:
    def __init__(self, name: str, age: int):
        self.name = name
        self.age = age

    def __repr__(self):
        return f"Person(name={self.name}, age={self.age})"

    def __eq__(self, other):
        return (self.name, self.age) == (other.name, other.age)

С dataclass:

from dataclasses import dataclass

@dataclass
class Person:
    name: str
    age: int

Теперь класс автоматически получает __init__, __repr__, __eq__!


Ключевые возможности

1. Параметры декоратора

  • frozen=True: делает объект неизменяемым (как namedtuple).
  • order=True: генерирует методы сравнения (__lt__, __gt__ и др.).
  • slots=True: оптимизация памяти через __slots__.
@dataclass(frozen=True, order=True)
class Point:
    x: float
    y: float

2. Значения по умолчанию

Можно задавать прямо в объявлении атрибутов:

@dataclass
class Config:
    timeout: int = 10
    verbose: bool = False

3. Поле field для кастомизации

Для сложных сценариев используйте field():

from dataclasses import field

@dataclass
class Student:
    name: str
    grades: list[int] = field(default_factory=list, repr=False)

Здесь grades инициализируется пустым списком и исключается из __repr__.


Продвинутые техники

1. Наследование

Датаклассы поддерживают наследование:

@dataclass
class Base:
    id: int

@dataclass
class User(Base):
    username: str

2. Методы в датаклассах

Можно добавлять свои методы как в обычный класс:

@dataclass
class Rectangle:
    width: float
    height: float

    def area(self) -> float:
        return self.width * self.height

3. Конвертация в кортеж/словарь

from dataclasses import asdict, astuple

rect = Rectangle(3.0, 4.0)
print(asdict(rect))  # ```> {'width': 3.0, 'height': 4.0}

Ограничения

  • Не для всех сценариев: если нужен полный контроль над поведением класса, dataclass может быть недостаточно.
  • Производительность: slots=True ускоряет доступ к атрибутам, но запрещает динамическое добавление полей.

Резюмируем

Dataclasses идеальны для:

  • Классов-моделей данных (DTO, Entity).
  • Уменьшения шаблонного кода.
  • Быстрого прототипирования.

Пример с подсветкой (как в VSCode):

from dataclasses import dataclass, field

@dataclass(order=True)
class Product:
    id: int
    name: str
    price: float = field(default=0.0, compare=False)
    tags: list[str] = field(default_factory=list)