Skip to content

Dataclasses Competent

🐍 Core Python Track · Level 2
⏱️ ~2 days 📚 Prerequisite: OOP Fundamentals

Basic usage

Basic usage in Dataclasses — what it is and when to use it.

from dataclasses import dataclass

@dataclass
class Point:
    x: float
    y: float

p = Point(3.0, 4.0)
print(p)               # Point(x=3.0, y=4.0)  — auto __repr__
print(p == Point(3.0, 4.0))   # True — auto __eq__

Default values & fields

Default values & fields in Dataclasses — what it is and when to use it.

from dataclasses import dataclass, field

@dataclass
class Config:
    host: str = "localhost"
    port: int = 8080
    tags: list = field(default_factory=list)   # mutable default

Frozen (immutable)

Frozen (immutable) in Dataclasses — what it is and when to use it.

@dataclass(frozen=True)
class Coordinate:
    lat: float
    lon: float

c = Coordinate(40.7, -74.0)
c.lat = 0   # FrozenInstanceError!

Post-init processing

Post-init processing in Dataclasses — what it is and when to use it.

@dataclass
class Circle:
    radius: float
    area: float = field(init=False)

    def __post_init__(self):
        self.area = 3.14159 * self.radius ** 2

Ordering & comparison

Ordering & comparison in Dataclasses — what it is and when to use it.

order=True generates __lt__, __le__, etc., comparing fields as a tuple:

from dataclasses import dataclass

@dataclass(order=True)
class Version:
    major: int
    minor: int

print(Version(1, 2) < Version(1, 5))   # True
print(sorted([Version(2, 0), Version(1, 9)]))
# [Version(major=1, minor=9), Version(major=2, minor=0)]

slots=True — smaller, faster instances

slots=True — smaller, faster instances, part of Dataclasses.

Python 3.10+ can generate __slots__, which drops the per-instance __dict__:

from dataclasses import dataclass

@dataclass(slots=True)
class Point:
    x: int
    y: int

p = Point(1, 2)
print(hasattr(p, "__dict__"))   # False — attributes live in slots

Excluding a field from compare / repr

Excluding a field from compare / repr in Dataclasses — what it is and when to use it.

from dataclasses import dataclass, field

@dataclass
class User:
    name: str
    password: str = field(repr=False, compare=False)

u = User("alice", "secret")
print(u)   # User(name='alice')  — password hidden from repr
print(u == User("alice", "different"))   # True — password ignored in ==

Convert to dict / tuple

Convert to dict / tuple in Dataclasses — what it is and when to use it.

from dataclasses import dataclass, asdict, astuple

@dataclass
class Point:
    x: int
    y: int

p = Point(3, 4)
print(asdict(p))    # {'x': 3, 'y': 4}
print(astuple(p))   # (3, 4)

Post-init validation (runnable)

Post-init validation (runnable) in Dataclasses — what it is and when to use it.

from dataclasses import dataclass, field

@dataclass
class Circle:
    radius: float
    area: float = field(init=False)

    def __post_init__(self):
        if self.radius < 0:
            raise ValueError("radius must be non-negative")
        self.area = 3.14159 * self.radius ** 2

c = Circle(2)
print(round(c.area, 2))   # 12.57

Practice exercises

  1. Convert a regular class with __init__, __repr__, __eq__ into a @dataclass.
  2. Create a frozen Color dataclass with RGB values and a computed hex property.
  3. Build a @dataclass with validation in __post_init__.
  4. Use order=True to make a Card dataclass sortable by rank then suit.
  5. Use asdict to serialize a nested dataclass to JSON.

💬 Discussion

Have a question about this topic? Found an error? Share your thoughts below.