Records#
Fixed-shape data with named fields. Three options, in increasing
weight: namedtuple for compact immutable rows, @dataclass
for any record with behaviour or mutation, TypedDict when the
record is really a JSON object the operator is annotating.
namedtuple#
Lightweight tuple subclass with named fields. Immutable. Compact memory, fast access. Use for return values and simple records.
from collections import namedtuple
Point = namedtuple("Point", "x y")
p = Point(3, 4)
p.x, p.y, p[0], p[1]
p._replace(x=10) # returns a new Point
dataclass#
Mutable by default, frozen with frozen=True. Supports
defaults, type hints, __post_init__, slots, comparison
methods.
from dataclasses import dataclass, field
@dataclass(frozen=True, slots=True)
class Target:
host: str
port: int = 443
tags: tuple[str, ...] = ()
frozen=True makes the instance hashable and immutable;
slots=True drops the per-instance __dict__ and shaves
memory.
TypedDict#
A dict subclass with statically declared key types. Use
when the data structure is a JSON object and a real class would be
over-engineering.
from typing import TypedDict
class Scan(TypedDict):
host: str
port: int
open: bool
s: Scan = {"host": "example.com", "port": 443, "open": True}