Dataclasses: упрощение создания классов данных (Python 3.7+)

Когда обычные классы становятся слишком многословными 💬

Представьте, что вы пишете класс для представления точки в 3D-пространстве. Стандартный вариант выглядит так:

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

    def __repr__(self):
        return f"Point(x={self.x}, y={self.y}, z={self.z})"

    def __eq__(self, other):
        return (self.x, self.y, self.z) == (other.x, other.y, other.z)

Сколько шаблонного кода! И это ещё без методов __lt__, __hash__ и других.

Dataclasses решают эту проблему — они автоматически генерируют "магические" методы на основе аннотаций типов.


Базовый пример: превращаем 20 строк в 3 🪄

Вот тот же класс Point, написанный с использованием @dataclass:

from dataclasses import dataclass

@dataclass
class Point:
    x: float
    y: float
    z: float

Вот что автоматически добавит декоратор: - __init__() - __repr__() - __eq__()

Проверим:

p1 = Point(1.0, 2.0, 3.0)
p2 = Point(1.0, 2.0, 3.0)
print(p1)  # Point(x=1.0, y=2.0, z=3.0)
print(p1 == p2)  # True

Настройка поведения через параметры 🎛️

Декоратор @dataclass принимает полезные параметры:

@dataclass(order=True, frozen=True)
class Card:
    rank: str
    suit: str
  • order=True — генерирует методы сравнения (__lt__, __le__ и др.)
  • frozen=True — делает объект неизменяемым (как namedtuple)

Пример использования:

queen = Card('Q', 'Hearts')
king = Card('K', 'Spades')
print(queen < king)  # True ('Q' < 'K' в лексикографическом порядке)
queen.rank = 'A'  # Ошибка: нельзя изменить замороженный dataclass

Продвинутые фишки: от mutable по умолчанию до наследования 🔧

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

@dataclass
class User:
    name: str
    age: int = 0  # Поле с дефолтным значением
    active: bool = True

Поле с фабричной функцией

from dataclasses import field
import uuid

@dataclass
class Transaction:
    id: str = field(default_factory=lambda: uuid.uuid4().hex)
    amount: float

Наследование dataclass

@dataclass
class Person:
    name: str
    age: int

@dataclass
class Employee(Person):
    employee_id: str
    salary: float

Когда использовать (а когда — нет) ⚖️

Идеальные случаи:

  • Классы-контейнеры данных (DTO, модели)
  • Замена namedtuple с изменяемостью
  • Там, где нужна "правильная" реализация __repr__ и __eq__

Не подходит:

  • Для классов с сложной бизнес-логикой
  • Когда нужно полное управление всеми методами
  • В очень старых проектах (Python < 3.7)

Бонус: dataclass vs namedtuple vs attrs 🥊

Характеристика dataclass namedtuple attrs
Изменяемость Да Нет Да
Поддержка типов Отлично Нет Да
Доп. функциональность Средняя Минимальная Богатая
Встроен в Python Да (3.7+) Да Нет

Совет от Данилы Бежина: Начните с dataclass — это золотая середина для большинства задач. Подробнее на YouTube-канале.

Скрыть рекламу навсегда

🎥 YouTube: программирование простым языком

Канал, где я спокойно и по шагам объясняю сложные темы — без заумных терминов и лишней теории.

Подходит, если раньше «не заходило», но хочется наконец понять.

▶️ Смотреть курсы на YouTube