Skip to content

__slots__

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.

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 attribute
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 attributes
  • Lower memory per instance: no per-instance __dict__ means noticeably less memory when creating millions of small objects (a Point-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 for self.z) fails loudly instead of silently creating an unintended new attribute.
  • __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 for weakref and 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).
  1. What does declaring __slots__ = ("x", "y") prevent?

    AnswerSetting any attribute other than `x` and `y` on an instance β€” it raises `AttributeError`, and the instance also has no `__dict__` at all.
  2. Why would you use __slots__ on a class you’re instantiating a million times?

    AnswerTo meaningfully reduce per-instance memory overhead by skipping the per-instance `__dict__`, and to get slightly faster attribute access.
  3. If a subclass of a __slots__ class doesn’t declare its own __slots__, does it still avoid __dict__?

    AnswerNo β€” the subclass gets a `__dict__` automatically unless it also declares `__slots__` (even an empty one), which reintroduces the per-instance overhead for that subclass.