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-канале.