Перейти к основному содержимому

Dataclasses: компактные классы с данными

dataclasses упрощают создание классов‑контейнеров данных: автоматически генерируют __init__, __repr__, __eq__ и другие методы. Меньше шаблонного кода — выше читаемость и меньше шансов на ошибки.

Базовый пример: меньше кода, больше пользы

from dataclasses import dataclass


@dataclass
class Player:
name: str
age: int
team: str


p = Player('Иван', 17, 'Метеор')
print(p) # авто-__repr__
print(p.name, p.age)
q = Player('Иван', 17, 'Метеор')
print(p == q) # авто-__eq__ сравнивает по полям
Player(name='Иван', age=17, team='Метеор')
Иван 17
True

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

Для изменяемых полей (списки, словари) используйте default_factory, чтобы у каждого экземпляра было своё значение по умолчанию.

from dataclasses import dataclass, field


@dataclass
class Player:
name: str
age: int
team: str
goals: int = 0
history: list[str] = field(default_factory=list)


p1 = Player('Иван', 17, 'Метеор')
p2 = Player('Павел', 18, 'Вымпел')

p1.history.append('Гол в финале')
print(p1.history)
print(p2.history) # независимый список
['Гол в финале']
[]

Неподвижные объекты: frozen=True

Immutability помогает избегать случайных изменений. С frozen=True попытка изменить поле приводит к ошибке.

from dataclasses import dataclass, FrozenInstanceError


@dataclass(frozen=True)
class FrozenPlayer:
name: str
age: int
team: str


fp = FrozenPlayer('Иван', 17, 'Метеор')
print(fp)
try:
fp.age = 18
except FrozenInstanceError as e:
print('Ошибка:', type(e).__name__)
FrozenPlayer(name='Иван', age=17, team='Метеор')
Ошибка: FrozenInstanceError

Мини‑памятка

  • @dataclass генерирует __init__, __repr__, __eq__ и др. на основе полей.
  • Для изменяемых значений применяйте field(default_factory=...) (а не обычный дефолт).
  • frozen=True делает экземпляры неизменяемыми (удобно для «значимых» объектов/ключей).
  • Dataclasses хорошо подходят для «DTO‑подобных» структур, оставляя при этом возможность добавлять методы.