How to Reduce Instance Memory with __slots__ in Python
Demonstrates that classes with __slots__ use less memory per instance than regular classes because they skip the instance __dict__.
Python code
25 linesclass SlottedPoint:
__slots__ = ('x', 'y', 'z')
def __init__(self, x, y, z):
self.x = x
self.y = y
self.z = z
class RegularPoint:
def __init__(self, x, y, z):
self.x = x
self.y = y
self.z = z
if __name__ == "__main__":
regular = RegularPoint(1, 2, 3)
slotted = SlottedPoint(1, 2, 3)
print(f"RegularPoint instance size: {regular.__sizeof__()} bytes")
print(f"SlottedPoint instance size: {slotted.__sizeof__()} bytes")
print(f"Memory saved: {regular.__sizeof__() - slotted.__sizeof__()} bytes")
print(f"RegularPoint has __dict__: {hasattr(regular, '__dict__')}")
print(f"SlottedPoint has __dict__: {hasattr(slotted, '__dict__')}")
Output
RegularPoint instance size: 56 bytes
SlottedPoint instance size: 48 bytes
Memory saved: 8 bytes
RegularPoint has __dict__: True
SlottedPoint has __dict__: False
How it works
The __slots__ declaration tells Python to pre-allocate a fixed set of attributes for each instance, replacing the per-instance __dict__ dictionary with a more compact descriptor-based storage. That's why the slotted instance reports no __dict__ and consistently returns the same sizeof value, while regular instances each carry their own dict overhead. The savings scale with the number of instances — for millions of objects, a few dozen bytes each can dramatically shrink memory usage. Note that __slots__ also prevents adding new attributes not listed, which enforces a stricter, more predictable object model.
Common mistakes
- Forgetting that __slots__ must be an iterable of strings, not a single string
- Expecting slotted instances to have __dict__ or be picklable without extra effort
- Overlooking that inheritance requires redeclaring __slots__ in every subclass
Variations
- Use `__slots__ = 'x y z'.split()` for a more readable declaration when there are many fields
- Add `__weakref__` to __slots__ if you need weak references to your instances
Real-world use cases
- Storing millions of lightweight vector points or coordinates in a scientific simulation.
- Representing large datasets of record-like objects in memory‑constrained analytics pipelines.
- Caching many small, fixed‑shape objects (like API responses or config entries) in a production service.
Sponsored
More from Concurrency & performance
- Benchmark list.append vs deque.append in Python medium
- Build a Python Performance Profiler That Generates Readable Reports medium
- Graceful Shutdown Executor Context Manager in Python medium
- How to Build a Producer-Consumer Pattern with asyncio.Queue in Python medium
- How to Cancel an asyncio Task with Graceful Cleanup in Python medium
- How to Convert Data in Parallel with ThreadPoolExecutor in Python easy
Keep learning
Related tutorials and quizzes for this topic.