Large numbers of instances and many-field constructors are where these options pay off.
`slots=True` (3.10+) generates a class with __slots__ for its fields. Instances then have no per-instance __dict__:
- noticeably less memory per instance, which matters for millions of objects,
- slightly faster attribute access,
- assigning an attribute that isn't a field raises
AttributeError, which catches typos.
Because __slots__ must exist at class creation, the decorator builds a new class. Consequences: anything that captured the original class before the swap (for example a registry filled by a decorator applied underneath) points at the old class, and weak references need weakref_slot=True (3.11).
Keyword-only fields make call sites self-documenting and remove the default-ordering restriction:
@dataclass(kw_only=True)makes every field keyword-only.field(kw_only=True)marks individual fields.- A pseudo-field
_: KW_ONLYmakes all fields after it keyword-only.
Keyword-only fields are moved after positional ones in __init__, so a required keyword-only field may follow a field with a default. That's the clean fix for inheritance ordering problems (next lesson).
Config(host="x", port=1, debug=True) reads far better than Config("x", 1, True); use keyword-only for anything beyond two or three fields.
Example
import sys
from dataclasses import dataclass, KW_ONLY
@dataclass
class PlainPoint:
x: float; y: float
@dataclass(slots=True)
class SlotPoint:
x: float; y: float
p, s = PlainPoint(1, 2), SlotPoint(1, 2)
print(hasattr(p, "__dict__"), hasattr(s, "__dict__")) # True False
print(sys.getsizeof(p) + sys.getsizeof(p.__dict__), sys.getsizeof(s)) # e.g. 344 48
try:
s.z = 3
except AttributeError as e:
print("typo caught:", e) # 'SlotPoint' object has no attribute 'z' ...
@dataclass
class Request:
url: str
_: KW_ONLY
timeout: float = 10.0
retries: int # required, allowed after a default because kw-only
print(Request("https://x.io", retries=2)) # Request(url='https://x.io', timeout=10.0, retries=2)Remember
- slots=True removes __dict__: less memory, faster access, typo protection
- slots=True returns a new class; use weakref_slot=True for weak references
- kw_only=True, field(kw_only=True) or _: KW_ONLY make fields keyword-only
Watch out for
- Adding attributes dynamically to slotted instances, which raises AttributeError.