# Python slots **Python slots** restrict which attributes an instance can have by defining `__slots__` in a class. Instead of storing attributes in a flexible dictionary, instances with slots use fixed memory for only those attributes, reducing memory overhead and improving attribute access speed. Use slots for large numbers of instances with few attributes, or when memory usage matters (data structures, game entities, ML datasets). ## Example This example shows memory savings and access patterns with slots. ```python # run: python3 slots.py # description: __slots__ for memory-efficient instances import sys class WithoutSlots: def __init__(self, x, y): self.x = x self.y = y class WithSlots: __slots__ = ['x', 'y'] def __init__(self, x, y): self.x = x self.y = y # Create instances no_slots = WithoutSlots(1, 2) with_slots = WithSlots(1, 2) # Compare memory usage print(f"Without slots: {sys.getsizeof(no_slots.__dict__)} bytes for __dict__") print(f"With slots: no __dict__ (fixed memory layout)") print(f"Instance without slots: {sys.getsizeof(no_slots)} bytes") print(f"Instance with slots: {sys.getsizeof(with_slots)} bytes") # Try adding dynamic attributes try: with_slots.z = 3 except AttributeError as e: print(f"Error: {e}") # Slots instance is also faster to access obj1 = WithoutSlots(10, 20) obj2 = WithSlots(10, 20) print(f"Without slots x: {obj1.x}") print(f"With slots x: {obj2.x}") ``` ## Common patterns **Defining slots**: - `__slots__ = ['attr1', 'attr2']`: tuple or list of allowed attribute names - No `__dict__` created; attributes stored in fixed array - Subclasses inherit parent's slots; can add more with their own `__slots__` **Special cases**: - Slot names can use descriptors for custom behavior - `__dict__` can be included in slots to allow dynamic attributes: `__slots__ = ['x', '__dict__']` - `__weakref__` in slots if weak references are needed **Trade-offs**: - **Pro**: ~40% memory savings per instance for typical objects - **Pro**: Faster attribute access (direct array indexing vs dictionary lookup) - **Pro**: Prevents typos (`obj.lenght = 5` raises AttributeError instead of creating attribute) - **Con**: Can't add attributes dynamically after class definition - **Con**: Inheritance can get complex with slots in parent and child - **Con**: Slots are class-level; instances can't have different slots **When to use**: - Large collections of objects (thousands or millions) - Data structures with many instances but few attributes each - Performance-critical inner loops - Want to catch typos in attribute names **When to avoid**: - Small number of objects - Need dynamic attributes - Early in development (premature optimization) - Simple scripts or one-off code