In Python, every object has a dynamic dictionary (__dict__
) that stores its attributes. While flexible, this can consume more memory and slow down attribute access.
__slots__
helps reduce memory usage by preventing the creation of __dict__
and restricting attributes to a fixed set.
Improves attribute lookup speed by avoiding dictionary overhead.
Useful for performance optimization in applications with many instances.
1. Understanding __slots__
By default, Python classes use a dictionary (__dict__
) to store attributes dynamically.
Example: Regular Class with __dict__
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
p = Person("Alice", 30)
print(p.__dict__)
# Output: {'name': 'Alice', 'age': 30}
Problem:
- Each instance has a
__dict__
, consuming extra memory. - Attribute lookup is slower due to dictionary overhead.
2. Using __slots__
to Optimize Memory Usage
The __slots__
attribute restricts instances to a fixed set of attributes and removes the __dict__
.
Example: Defining __slots__
class Person:
__slots__ = ('name', 'age') # Restrict attributes
def __init__(self, name, age):
self.name = name
self.age = age
p = Person("Alice", 30)
print(p.name) # Output: Alice
# p.address = "NYC" # AttributeError: 'Person' object has no attribute 'address'
What happens here?
- No
__dict__
→ Memory-efficient storage. - Restricted attributes → Only
name
andage
are allowed. - Faster attribute access → Directly stored in a lightweight structure.
3. Comparing Memory Usage (__dict__
vs __slots__
)
Using sys.getsizeof()
to measure memory usage.
Example: Memory Comparison
import sys
class Regular:
def __init__(self, x):
self.x = x
class Slotted:
__slots__ = ('x')
def __init__(self, x):
self.x = x
r = Regular(10)
s = Slotted(10)
print(sys.getsizeof(r.__dict__)) # Output: 112 (dict overhead)
# print(s.__dict__) # AttributeError: No __dict__ (saves memory)
Why does __slots__
save memory?
- Regular class: Stores attributes in a dictionary (
__dict__
), which has overhead. - Slotted class: Uses a tuple-like structure (lower memory footprint).
4. When to Use __slots__
Use __slots__
when:
- You need thousands/millions of objects (e.g., data-heavy applications).
- Memory optimization is a priority.
- Your class has fixed attributes (no dynamic attributes needed).
Avoid __slots__
when:
- You require dynamic attributes (e.g., adding attributes at runtime).
- You need multiple inheritance (not well-supported with
__slots__
). - You frequently use
dir()
,vars()
, or other reflection methods (which rely on__dict__
).
5. Inheritance and __slots__
5.1 Single Inheritance with __slots__
When a subclass inherits a slotted class, it can define new slots.
class Parent:
__slots__ = ('a',)
class Child(Parent):
__slots__ = ('b',)
obj = Child()
obj.a = 10
obj.b = 20
# obj.c = 30 # AttributeError: 'Child' object has no attribute 'c'
Each class must define its own __slots__
for new attributes.
5.2 __slots__
with Multiple Inheritance (Limitations)
Python does not allow multiple slotted parent classes without a fallback __dict__
.
class A:
__slots__ = ('x',)
class B:
__slots__ = ('y',)
class C(A, B): # Error: Multiple inheritance with slots
pass
Solution: Use __slots__ = ('x', 'y')
in C
OR avoid __slots__
in multiple-inheritance scenarios.
6. Allowing __dict__
with __slots__
If needed, you can explicitly allow dynamic attributes while keeping __slots__
benefits.
class Config:
__slots__ = ('setting1', 'setting2', '__dict__')
cfg = Config()
cfg.setting1 = "ON"
cfg.new_attr = "Allowed" # Now works, because __dict__ is present
Why?
__dict__
is re-enabled, allowing dynamic attributes.__slots__
still optimizes existing attributes.
7. Summary Table
Feature | Without __slots__ | With __slots__ |
---|---|---|
Memory Usage | Higher (uses __dict__ ) | Lower (no __dict__ ) |
Attribute Access | Slower (dictionary lookup) | Faster (direct access) |
Dynamic Attributes | Allowed | Not allowed (unless __dict__ is explicitly added) |
Multiple Inheritance | Works normally | Limited support |
Reflection (dir() , vars() ) | Works as expected | May not work correctly |