Lesson 5 / 25

Tuples, namedtuple and dataclasses

Choose between tuples, named tuples and dataclasses for records.

Fixed-shape records

A tuple is an immutable sequence. Because it cannot change, a tuple of hashable values is itself hashable, so it can be a dictionary key or a set member (for example, (row, col) coordinates). Tuples are slightly smaller and faster to create than lists, support unpacking (name, score = pair) and are the natural return type for multiple values. For readable records, collections.namedtuple or typing.NamedTuple adds field names while staying a tuple (immutable, indexable, lightweight). dataclasses.dataclass generates __init__, __repr__ and __eq__ for regular classes; options include frozen=True (immutable and hashable), order=True (comparison methods), slots=True (Python 3.10+, less memory and faster attribute access) and field(default_factory=list) for mutable defaults. Use tuples for small, fixed groupings and keys, named tuples for lightweight immutable records, and dataclasses when you want methods, defaults, type hints and optional mutability. Libraries such as attrs and Pydantic (with validation) offer more features.

Records three ways

Tuples as keys, NamedTuple and a slotted dataclass.

from dataclasses import dataclass, field
from typing import NamedTuple

# tuple as a dictionary key
seat_prices = {(1, "A"): 1200, (1, "B"): 1200, (10, "C"): 800}
print(seat_prices[(1, "A")])                  # 1200

class Point(NamedTuple):
    lat: float
    lng: float

pune = Point(18.52, 73.86)
lat, lng = pune                               # still a tuple: unpacks
print(pune.lat, pune[1])                      # 18.52 73.86

@dataclass(slots=True)
class Order:
    order_id: str
    city: str
    items: list[str] = field(default_factory=list)   # safe mutable default
    paid: bool = False

    def add(self, sku: str) -> None:
        self.items.append(sku)

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

o = Order("o-1", "Pune")
o.add("pen")
print(o)                                      # Order(order_id='o-1', city='Pune', items=['pen'], paid=False)
print(sorted([Version(1, 10), Version(1, 2)]))   # [Version(major=1, minor=2), Version(major=1, minor=10)]
print({Version(2, 0): "current"})             # frozen dataclasses are hashable

A printed form versus a notebook

A tuple is a printed form: fixed fields that cannot be changed once filled in, which makes it safe to file under an index (a dict key). A dataclass is a notebook template with labelled pages that you can keep editing.

Quick check: Why can a tuple of strings be used as a dictionary key while a list cannot?

  • Tuples are faster
  • Tuples are immutable and hashable; lists are mutable and unhashable
  • Lists cannot hold strings
  • Dictionaries only accept tuples
Answer

Tuples are immutable and hashable; lists are mutable and unhashable — Keys must be hashable, and their hash must not change.