__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__`.