__slots__
__slots__
Section titled β__slots__βWhat it is
Section titled βWhat it isβBy default, every instance of a Python class carries a __dict__ β a per-instance dictionary holding its attributes β which is flexible (attributes can be added dynamically) but has real memory overhead per object. __slots__ is a class attribute (a list/tuple of allowed attribute names) that tells Python to skip creating __dict__ and instead allocate fixed, fast storage only for those named attributes.
Before this feature
Section titled βBefore this featureβclass Point: def __init__(self, x, y): self.x = x self.y = y
p = Point(1, 2)print(p.__dict__) # {'x': 1, 'y': 2} -- a real dict, one per instance
p.z = 3 # works fine β nothing stops adding a new attributeAfter this feature
Section titled βAfter this featureβclass Point: __slots__ = ("x", "y")
def __init__(self, x, y): self.x = x self.y = y
p = Point(1, 2)# p.__dict__ # AttributeError: 'Point' object has no attribute '__dict__'
p.z = 3 # AttributeError: 'Point' object has no attribute 'z' # __slots__ enforces exactly the declared attributesWhy this is better
Section titled βWhy this is betterβ- Lower memory per instance: no per-instance
__dict__means noticeably less memory when creating millions of small objects (aPoint-like class with__slots__can use roughly half the memory of the equivalent__dict__-based class). - Slightly faster attribute access: slot attributes are stored in a fixed-size structure rather than looked up in a dict, which is marginally faster.
- Catches typos as errors:
self.zc = 3(a typo forself.z) fails loudly instead of silently creating an unintended new attribute.
Key notes / edge cases
Section titled βKey notes / edge casesβ__slots__must be redeclared in every subclass that adds new attributes β a subclass that doesnβt declare__slots__gets a__dict__anyway (defeating the purpose for that subclass), and even a subclass that does declare it inherits the parentβs slots plus its own.- You canβt set a default value directly in
__slots__β__slots__ = ("x", "y")just names the allowed attributes; defaults still go through__init__. - A class with
__slots__canβt use class-level attributes with the same name as a slot, and by default loses support forweakrefand multiple inheritance from more than one slotted class with non-empty slots β usually not a problem in practice, but worth knowing. - Not worth using for every class β it trades away dynamic flexibility (no adding attributes at runtime) for memory/speed, so it matters most for classes youβll instantiate in large numbers (data records, not one-off config objects).
Quick practice
Section titled βQuick practiceβ-
What does declaring
__slots__ = ("x", "y")prevent?Answer
Setting any attribute other than `x` and `y` on an instance β it raises `AttributeError`, and the instance also has no `__dict__` at all. -
Why would you use
__slots__on a class youβre instantiating a million times?Answer
To meaningfully reduce per-instance memory overhead by skipping the per-instance `__dict__`, and to get slightly faster attribute access. -
If a subclass of a
__slots__class doesnβt declare its own__slots__, does it still avoid__dict__?Answer
No β the subclass gets a `__dict__` automatically unless it also declares `__slots__` (even an empty one), which reintroduces the per-instance overhead for that subclass.