Writing boilerplate code for classes that mainly store data is tedious and error-prone. Dataclasses automatically generate init, repr, and eq methods from type-annotated fields, reducing code while maintaining full type safety and IDE support.

Why Use Dataclasses?

Comparison and Ordering

Use order=True to enable comparison operators based on field values.

basic.py
# Basic dataclass definition

from dataclasses import dataclass

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

# Create instances - __init__ is auto-generated
person1 = 
person2 = Person("Bob", 25, "bob@example.com")

# __repr__ is auto-generated
print(person1)

# __eq__ is auto-generated
print(person1 == person2)  # False
print(person1 == Person(person1.name, person1.age, person1.email))  # True
# Basic dataclass definition

from dataclasses import dataclass

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

# Create instances - __init__ is auto-generated
person1 = 
person2 = Person("Bob", 25, "bob@example.com")

# __repr__ is auto-generated
print(person1)

# __eq__ is auto-generated
print(person1 == person2)  # False
print(person1 == Person(person1.name, person1.age, person1.email))  # True
# Basic dataclass definition

from dataclasses import dataclass

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

# Create instances - __init__ is auto-generated
person1 = 
person2 = Person("Bob", 25, "bob@example.com")

# __repr__ is auto-generated
print(person1)

# __eq__ is auto-generated
print(person1 == person2)  # False
print(person1 == Person(person1.name, person1.age, person1.email))  # True
default_values.py
# Dataclass with default values

from dataclasses import dataclass

@dataclass
class Product:
    name: str
    price: float
    quantity: int = 0
    in_stock: bool = True
    category: str = "General"

# Use defaults
product1 = Product("Laptop", 999.99)
print(product1)

# Override defaults
product2 = Product("Mouse", 29.99, quantity=50, category="Electronics")
print(product2)

# Out of stock product
product3 = Product("Phone", 599.99, in_stock=False)
print(product3)
frozen.py
# Frozen dataclasses (immutable)

from dataclasses import dataclass

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

# Create point
point = Point(10.5, 20.3)
print(f"Point: ({point.x}, {point.y})")

# Cannot modify - will raise FrozenInstanceError
try:
    point.x = 100
except AttributeError as e:
    print(f"Error: {e}")

# Can use as dictionary keys (hashable)
points_dict = {
    Point(0, 0): "origin",
    Point(10, 10): "ten-ten",
    Point(5, 5): "five-five"
}
print(points_dict[Point(0, 0)])
field_factory.py
# Using field() for mutable defaults

from dataclasses import dataclass, field

@dataclass
class ShoppingCart:
    customer: str
    items: list = field(default_factory=list)
    total: float = 0.0
    
    def add_item(self, item: str, price: float):
        self.items.append(item)
        self.total += price

# Each cart gets its own list
cart1 = ShoppingCart("Alice")
cart1.add_item("Apple", 1.50)
cart1.add_item("Banana", 0.75)

cart2 = ShoppingCart("Bob")
cart2.add_item("Orange", 2.00)

print(f"{cart1.customer}'s cart: {cart1.items}, Total: ${cart1.total:.2f}")
print(f"{cart2.customer}'s cart: {cart2.items}, Total: ${cart2.total:.2f}")
ordering.py
# Dataclass with ordering

from dataclasses import dataclass, field

@dataclass(order=True)
class Score:
    value: int
    player: str = field(compare=False)  # Don't use in comparison

# Create scores
scores = [
    Score(85, "Alice"),
    Score(92, "Bob"),
    Score(78, "Charlie"),
    Score(95, "David")
]

# Can compare
print(f"Bob's score > Alice's score: {scores[1] > scores[0]}")

# Can sort
sorted_scores = sorted(scores, reverse=True)
print("\nLeaderboard:")
for rank, score in enumerate(sorted_scores, 1):
    print(f"{rank}. {score.player}: {score.value}")

@seealso namedtuple_intro "NamedTuples for immutable data" @seealso typing_intro "Type hints"

dataclass A decorator that automatically generates special methods like __init__, __repr__, and __eq__ for classes that primarily store data, based on type-annotated class attributes.
frozen dataclass A dataclass with frozen=True that prevents attribute modification after creation, making instances immutable and hashable.
field() A function that provides fine-grained control over dataclass fields, including default_factory for mutable defaults and compare/hash options.

Exercise: practical.py

Create an AppConfig dataclass with feature toggles and configuration management methods