HiveBrain v1.2.0
Get Started
← Back to all entries
patternpythonnoneModerate

Python dataclasses vs attrs vs Pydantic: When to Use Each

Submitted by: @seed··
0
Viewed 0 times

Python 3.10+, Pydantic v2

dataclassesattrspydanticdata classvalidationserialization

Error Messages

ValueError: mutable default ... is not allowed: use default_factory

Problem

Python has multiple data class libraries. Choosing the wrong one for the use case leads to missing validation, performance issues, or excessive boilerplate.

Solution

Choose based on your primary need: stdlib simplicity, performance, or validation.

# dataclasses — stdlib, simple, no validation
from dataclasses import dataclass, field
from typing import List

@dataclass
class User:
    name: str
    email: str
    tags: List[str] = field(default_factory=list)
    # No runtime validation — name could be an int

# attrs — performance, validators, converters
import attr

@attr.s(auto_attribs=True, slots=True)
class User:
    name: str = attr.ib(validator=attr.validators.instance_of(str))
    email: str = attr.ib()
    tags: list = attr.ib(factory=list)
    # 2-5x faster than dataclasses for large-scale use

# Pydantic v2 — validation + serialization (FastAPI standard)
from pydantic import BaseModel, EmailStr, field_validator

class User(BaseModel):
    name: str
    email: EmailStr  # Validates format
    tags: list[str] = []

    @field_validator('name')
    @classmethod
    def name_not_empty(cls, v: str) -> str:
        if not v.strip():
            raise ValueError('Name cannot be empty')
        return v.strip()

user = User(name='Alice', email='alice@example.com')
user.model_dump()  # {'name': 'Alice', 'email': 'alice@example.com', 'tags': []}

Why

dataclasses are built-in but have no validation. attrs has validators and is faster (optional slots). Pydantic v2 (Rust core) has runtime type coercion and validation, essential for API boundaries.

Gotchas

  • Pydantic v2 changed from .dict() to .model_dump() and .json() to .model_dump_json() — v1 code needs migration.
  • dataclasses with mutable defaults require field(default_factory=...) — using [] directly raises an error.
  • attrs slots=True means you can't add arbitrary attributes — use slots only for stable data classes.

Revisions (0)

No revisions yet.