Датаклассы и именованные кортежи
Структурированные записи без шаблонного кода
Главная идея: Датакласс — это обычный класс, у которого повторяющийся служебный код —
__init__, __repr__, __eq__ и другие — генерируется за вас из полей с аннотациями типов. Именованный кортеж (namedtuple) — это неизменяемый кортеж, чьи позиции к тому же имеют имена. Оба позволяют ясно смоделировать небольшой набор связанных полей; дальше речь пойдёт о том, как выбрать нужный инструмент и управлять им через field() и frozen=True.
К концу вы сможете:
- заменить написанные вручную
__init__/__repr__/__eq__декоратором@dataclass, - безопасно задавать полям значения по умолчанию, включая изменяемые — через
field(default_factory=...), - делать записи неизменяемыми и хешируемыми с помощью
frozen=True, - настраивать отдельные поля через
field()(repr,compare,init,kw_only), - выбирать между датаклассом,
NamedTuple, обычным классом и словарём для конкретной задачи.
1. Проблема шаблонного кода
Вы уже умеете писать небольшой класс-запись вручную. Беда в том, что даже запись из трёх полей заставляет повторять каждое имя по три-четыре раза только ради разумного создания, вывода и сравнения.
class Point:
def __init__(self, x: float, y: float):
self.x = x
self.y = y
def __repr__(self):
return f"Point(x={self.x}, y={self.y})"
def __eq__(self, other):
if not isinstance(other, Point):
return NotImplemented
return (self.x, self.y) == (other.x, other.y)
Слишком много церемоний ради «x и y». Забудете __eq__ — и две равные точки окажутся неравными; забудете __repr__ — и в логах будет <Point object at 0x...>. Датаклассы генерируют именно этот служебный код из аннотаций.