Skip to content

slots and kw_only

The slots=True parameter reduces memory usage by preventing __dict__. The kw_only=True parameter requires keyword-only arguments in __init__().


Using slots=True

from dataclasses import dataclass

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

point = Point(1.0, 2.0)
print(point)  # Point(x=1.0, y=2.0)

# Attempt to add arbitrary attributes fails
try:
    point.z = 3.0
except AttributeError as e:
    print(f"Cannot add attribute: {e}")

# Check memory usage
print(f"Point size: {point.__sizeof__()} bytes")

Memory Efficiency with slots

from dataclasses import dataclass
import sys

# Without slots (has __dict__)
@dataclass
class RegularPoint:
    x: float
    y: float

# With slots (no __dict__)
@dataclass(slots=True)
class SlotPoint:
    x: float
    y: float

regular = RegularPoint(1.0, 2.0)
slot = SlotPoint(1.0, 2.0)

print(f"Regular: {sys.getsizeof(regular.__dict__)} bytes for __dict__")
print(f"Slotted: no __dict__, saves memory")

Using kw_only=True

from dataclasses import dataclass

@dataclass(kw_only=True)
class Configuration:
    host: str
    port: int
    timeout: float = 30.0

# Must use keyword arguments
config = Configuration(host="localhost", port=8080)
print(config)  # Configuration(host='localhost', port=8080, timeout=30.0)

# Positional arguments fail
try:
    bad_config = Configuration("localhost", 8080)
except TypeError as e:
    print(f"Error: {e}")

Combining slots and kw_only

from dataclasses import dataclass

@dataclass(slots=True, kw_only=True)
class OptimizedConfig:
    name: str
    debug: bool = False
    workers: int = 4

config = OptimizedConfig(name="production", debug=False)
print(config)  # OptimizedConfig(name='production', debug=False, workers=4)

# Memory efficient and requires keyword arguments

Per-Field kw_only

from dataclasses import dataclass, field

@dataclass
class MixedArgs:
    # Positional argument
    name: str

    # Keyword-only arguments
    age: int = field(kw_only=True)
    email: str = field(kw_only=True)

obj = MixedArgs("Alice", age=30, email="alice@example.com")
print(obj)  # MixedArgs(name='Alice', age=30, email='alice@example.com')

Performance with Slots

from dataclasses import dataclass
import timeit

@dataclass
class Regular:
    x: int
    y: int

@dataclass(slots=True)
class Slotted:
    x: int
    y: int

# Attribute access is slightly faster with slots
regular = Regular(1, 2)
slotted = Slotted(1, 2)

time_regular = timeit.timeit(lambda: regular.x, number=1000000)
time_slotted = timeit.timeit(lambda: slotted.x, number=1000000)

print(f"Regular: {time_regular:.4f}s")
print(f"Slotted: {time_slotted:.4f}s")

When to Use

  • slots=True: Large number of instances, memory matters
  • kw_only=True: Prevent positional argument confusion, improve code clarity
  • Both: Performance-critical code with many objects