Python известен своей элегантностью и удобством синтаксиса, который позволяет писать так называемый «приятный» код. В последних версиях языка появилось два инструмента, нацеленных именно на создание приятных объектных моделей: pydantic и dataclasses. Оба решают похожие задачи валидации и сериализации данных, но делают это немного по-разному. Давайте сравним их подходы, чтобы понять сильные и слабые стороны каждого.

photo.jpg

PYDANTIC VS DATACLASSES: СРАВНЕНИЕ ДЕКЛАРАТИВНОГО И ИМПЕРАТИВНОГО ПОДХОДОВ

Определение моделей
В pydantic модели определяются декларативно, через классы с типизированными атрибутами:

from pydantic import BaseModel

class User(BaseModel):
id: int
name: str
signup_ts: datetime = None

В dataclasses используется более императивный подход через декоратор:

from dataclasses import dataclass

@dataclass
class User:
id: int
name: str
signup_ts: datetime = None

Валидация
Pydantic проверяет типы и ограничения при создании модели:

user = User(id="test", signup_ts="bad date") # ошибка валидации

Dataclasses такой валидацией не обладают:

user = User(id="test", signup_ts="bad date") # ok

Сериализация

Pydantic позволяет с лёгкостью конвертировать объекты в JSON:

user = User(id=123)
json_str = user.json() # {'id': 123, 'name': None ...}

В dataclasses процесс сложнее и требует дополнительных библиотек:

# нужен импорт jsonpickle или другой custom encoder
json_str = jsonpickle.encode(user)

В данном примере pydantic выигрывает в объявлении типов и валидации при меньшей многословности кода. Dataclasses же лучше подходят для простых моделей, где важна скорость написания кода.

Иммутабельность

Pydantic модели по умолчанию неизменяемые (immutable):

user = User(id=1)
user.id = 2 # ошибка!

В то время как dataclass’ы можно менять:

user = User(1)
user.id = 2 # ok

Это может быть как плюсом, так и минусом в зависимости от задачи.

Дополнительная функциональность
У pydantic есть расширенные возможности:

Вложенные модели
Конфигурируемые поля
Управление наследованием
Пример вложенной модели:

class Address(BaseModel):
street: str

class User(BaseModel):
id: int
name: str
address: Address

В dataclasses подобное тоже можно реализовать:

@dataclass
class Address:
street: str

@dataclass
class User:
id: int
name: str
address: Address

Таким образом, pydantic позволяет гибко моделировать сложные структуры данных и иерархии классов.

Выводы
В целом:

Pydantic лучше подходит для: валидации, сериализации, сложных моделей
Dataclasses лучше когда нужна: простота, лёгкость, мутабельность