Difficulty: Advanced
What is __slots__ in Python? How does it improve memory and performance?
By default, each Python instance has a __dict__ dictionary to store attributes - flexible but memory-heavy.
__slots__ replaces __dict__ with a fixed-size array of slots for specified attributes. This: 1. Reduces memory by 30-50% per instance 2. Speeds up attribute access (array lookup vs dict lookup) 3. Prevents adding undeclared attributes at runtime
Best for: classes instantiated millions of times (data records, ORM rows, coordinate objects).
Limitations: cannot add new attributes at runtime, inheritance with __slots__ is complex, pickle/copy may need adjustments.
import sys
class PointDict:
def __init__(self, x, y):
self.x = x
self.y = y
class PointSlots:
__slots__ = ('x', 'y')
def __init__(self, x, y):
self.x = x
self.y = y
d = PointDict(1.0, 2.0)
s = PointSlots(1.0, 2.0)
print(sys.getsizeof(d.__dict__)) # ~104 bytes (dict overhead)
print(hasattr(s, '__dict__')) # False
print(sys.getsizeof(s)) # ~56 bytes (no dict)
# Cannot add undeclared attribute
try:
s.z = 3.0
except AttributeError as e:
print(e) # 'PointSlots' object has no attribute 'z'
# Performance comparison (millions of instances)
import timeit
def create_dict():
return [PointDict(i, i) for i in range(100000)]
def create_slots():
return [PointSlots(i, i) for i in range(100000)]
print('Dict:', timeit.timeit(create_dict, number=10))
print('Slots:', timeit.timeit(create_slots, number=10))
Slots use a fixed descriptor array instead of a hash table. Memory savings of ~50 bytes per instance are significant at scale.
class Base:
__slots__ = ('x',)
def __init__(self, x):
self.x = x
class Child(Base):
__slots__ = ('y',) # Only declare NEW slots
def __init__(self, x, y):
super().__init__(x)
self.y = y
c = Child(1, 2)
print(c.x, c.y) # 1 2
# If parent does NOT define __slots__, child gets __dict__
class RegularBase:
pass
class MixedChild(RegularBase):
__slots__ = ('x',)
m = MixedChild()
m.x = 1
m.z = 99 # Works! RegularBase provides __dict__
# Checking memory with dataclass slots (Python 3.10+)
from dataclasses import dataclass
@dataclass(slots=True)
class Coord:
x: float
y: float
z: float
import sys
print(sys.getsizeof(Coord(1.0, 2.0, 3.0)))
Child class only declares additional slots. If any base in the MRO lacks __slots__, a __dict__ is created anyway - defeating the purpose.
__slots__, __dict__, Memory, Attribute Access, Performance