Master Code
On The Go

Learn. Practice. Build.

Home › Code Snippets › Python Snippets › Dataclass

Python Snippet

Python Dataclass

Stop writing __init__, __repr__, and __eq__ by hand. Let @dataclass do it for you.

Last updated: October 2026

Quick answer: Add @dataclass above a class that stores data. Declare fields with type hints. Python auto-generates __init__, __repr__, and __eq__. For mutable defaults, use field(default_factory=list) instead of = [].

🎬 Interactive Live Demo

Click through the tabs to see how a regular class compares to its dataclass equivalent.

💡 Switch between tabs to see how much boilerplate @dataclass saves.

1

The Problem: Boilerplate Classes

A simple class that stores three fields requires a lot of repetitive code:

class User:
    def __init__(self, name, email, age):
        self.name = name
        self.email = email
        self.age = age

    def __repr__(self):
        return f"User(name={self.name!r}, email={self.email!r}, age={self.age!r})"

    def __eq__(self, other):
        if not isinstance(other, User):
            return NotImplemented
        return (self.name == other.name and
                self.email == other.email and
                self.age == other.age)

That's 18 lines to hold 3 fields. Multiply by every data class in your project.

2

The Solution: @dataclass

from dataclasses import dataclass

@dataclass
class User:
    name: str
    email: str
    age: int

Six lines. Same functionality. The decorator generates __init__, __repr__, and __eq__ automatically.

user = User("Alice", "alice@example.com", 30)
print(user)
# User(name='Alice', email='alice@example.com', age=30)

user2 = User("Alice", "alice@example.com", 30)
print(user == user2)  # True
3

Default Values and default_factory

For simple immutable defaults, use default:

@dataclass
class Product:
    name: str
    price: float = 0.0
    in_stock: bool = True

For mutable defaults like lists or dicts, use field(default_factory=...):

from dataclasses import dataclass, field

@dataclass
class User:
    name: str
    tags: list[str] = field(default_factory=list)
    metadata: dict = field(default_factory=dict)

Why not tags: list = []? Python raises ValueError at class definition time. Mutable defaults would be shared across all instances — the classic "list gets mutated everywhere" bug. default_factory creates a new list for each instance.

4

Frozen Dataclasses (Immutable)

Add frozen=True to make instances immutable and hashable:

from dataclasses import dataclass

@dataclass(frozen=True)
class Point:
    x: float
    y: float

p = Point(1.0, 2.0)
p.x = 5.0  # ❌ FrozenInstanceError

# Hashable — can be used as dict keys or in sets
cache = {p: "value"}

Frozen dataclasses are perfect for configuration objects, value types, and cache keys.

5

Adding Methods and Properties

Dataclasses are regular classes — add any methods you want:

@dataclass
class Product:
    name: str
    price: float
    tax_rate: float = 0.1

    @property
    def total(self) -> float:
        return self.price * (1 + self.tax_rate)

    def is_expensive(self) -> bool:
        return self.price > 100

p = Product("Laptop", 1200)
print(p.total)  # 1320.0
print(p.is_expensive())  # True
6

Real-World Use Case: API Response Models

from dataclasses import dataclass, field
from datetime import datetime
import json

@dataclass
class APIUser:
    id: int
    name: str
    email: str
    created_at: datetime = field(default_factory=datetime.now)
    tags: list[str] = field(default_factory=list)

    @classmethod
    def from_json(cls, data: dict):
        return cls(
            id=data["id"],
            name=data["name"],
            email=data["email"],
            tags=data.get("tags", [])
        )

# Parsing an API response becomes trivial
user = APIUser.from_json({
    "id": 1,
    "name": "Alice",
    "email": "alice@example.com"
})

Dataclasses make parsing external data clean and typed. Combined with field(default_factory=...), they handle the common "missing optional field" case gracefully.

🎯 Dataclass vs Regular Class vs NamedTuple vs Pydantic

Feature dataclass Regular Class Pydantic
Boilerplate Minimal High Minimal
Runtime Validation No No Yes
Dependencies Stdlib only Stdlib only Requires pydantic
Best For Internal data, DTOs Complex behavior API inputs, config

Choose @dataclass for internal data. Choose Pydantic when you need runtime validation (especially for API request bodies). Both are excellent — use them together in the same project.

⚠️ Common Mistakes

❓ Frequently Asked Questions

What is a dataclass in Python?

A dataclass is a Python decorator that automatically generates common methods like __init__, __repr__, and __eq__ for classes that primarily store data. It eliminates boilerplate and makes your code cleaner.

When should I use a dataclass?

Use dataclasses for any class that primarily holds data: configuration objects, API responses, DTOs, and simple domain models. If a class does more than store data, a regular class may be clearer.

What is the difference between default and default_factory?

default sets a fixed value shared by all instances. default_factory is a callable that creates a new value for each instance, which is required for mutable defaults like lists, dicts, and sets.

Can dataclasses have methods?

Yes. Dataclasses are regular classes. You can add any methods, properties, or class methods you want. The @dataclass decorator only auto-generates __init__, __repr__, and __eq__.

Are dataclasses faster than regular classes?

They are not faster at runtime, but they are faster to write. The generated methods are functionally identical to what you'd write by hand. The benefit is in developer time and code clarity.

🎯 What's Next?

← All Python Snippets