Modern Python Types
Dataclass Introduction
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