Phase 8 of 25 · Topic 8.5

__slots__ Memory Optimization for High-Density Objects

1Concept

By default, Python objects store attributes in a dynamic `__dict__` dictionary (~104 bytes per instance). Declaring `__slots__` tells CPython to use a fixed array of pointers instead of `__dict__`, saving up to 60% memory on millions of instances and preventing dynamic attribute injection.

2Architecture Diagram

Standard Object: [ PyObject Header ] + [ __dict__ Hash Table (~104B) ]
__slots__ Object: [ PyObject Header ] + [ Fixed Pointer Array (~48B total!) ]

3Code Example

Python 3.12
import sys

class StandardPoint:
    def __init__(self, x, y):
        self.x, self.y = x, y

class SlottedPoint:
    __slots__ = ('x', 'y')
    def __init__(self, x, y):
        self.x, self.y = x, y

std_pt = StandardPoint(10, 20)
slt_pt = SlottedPoint(10, 20)

print(f"Standard Point footprint: {sys.getsizeof(std_pt) + sys.getsizeof(std_pt.__dict__)} bytes")
print(f"Slotted Point footprint:  {sys.getsizeof(slt_pt)} bytes (No __dict__!)")

try:
    slt_pt.z = 30 # Blocked: no dynamic attribute allowed!
except AttributeError as e:
    print(f"Dynamic attribute blocked: {e}")

4Expected Output

Standard Point footprint: 152 bytes
Slotted Point footprint:  48 bytes (No __dict__!)
Dynamic attribute blocked: 'SlottedPoint' object has no attribute 'z'

5Key Takeaways

  • `__slots__` prevents the creation of `__dict__` and `__weakref__` unless explicitly declared.
  • Yields massive RAM savings when managing millions of small objects (e.g. data points, coordinates).
  • Subclasses must declare their own `__slots__` or they will re-introduce `__dict__`.