Complete guide to Python's __slots__ method covering memory optimization, attribute restriction, and performance benefits.
Last modified April 8, 2025
This comprehensive guide explores Python’s slots attribute, a special class variable that optimizes memory usage and restricts attribute creation. We’ll cover basic usage, memory benefits, inheritance, and practical examples.
The slots class variable is used to explicitly declare instance attributes. It serves two main purposes: memory optimization and attribute restriction. When defined, it prevents the creation of dict.
Key characteristics: it must be a sequence (usually tuple) of strings, saves memory by avoiding per-instance dictionaries, and restricts dynamic attribute creation. It’s particularly useful for classes with many instances.
Here’s the simplest implementation showing how slots restricts attribute creation and optimizes memory usage. It demonstrates the core behavior.
basic_slots.py
class Point: slots = (‘x’, ‘y’)
def __init__(self, x, y):
self.x = x
self.y = y
p = Point(3, 4) print(p.x, p.y) # Works fine
This example shows a Point class with fixed attributes x and y. Attempting to create a new attribute z would raise an AttributeError. The class doesn’t have a dict attribute.
The memory savings come from not having a per-instance dictionary to store attributes. Instead, attributes are stored in a more compact internal structure.
slots significantly reduces memory usage for classes with many instances. This example demonstrates the memory difference with and without it.
memory_optimization.py
import sys
class RegularPoint: def init(self, x, y): self.x = x self.y = y
class SlotPoint: slots = (‘x’, ‘y’) def init(self, x, y): self.x = x self.y = y
regular = RegularPoint(3, 4) slot = SlotPoint(3, 4)
print(sys.getsizeof(regular) + sys.getsizeof(regular.dict)) print(sys.getsizeof(slot)) # Typically much smaller
The SlotPoint class uses significantly less memory than RegularPoint. The difference becomes more noticeable when creating thousands or millions of instances.
Memory savings come from two sources: no dict allocation and more efficient attribute storage. The exact savings depend on Python version.
When using inheritance with slots, special care must be taken. Child classes must declare their own slots to add new attributes.
inheritance.py
class Base: slots = (‘a’,)
class Child(Base): slots = (‘b’,) # Only contains ‘b’, ‘a’ is from parent
def __init__(self, a, b):
self.a = a
self.b = b
obj = Child(1, 2) print(obj.a, obj.b)
The Child class inherits from Base but adds its own attribute b. The combined slots are a and b. Without declaring slots in Child, instances would get dict.
If a child class doesn’t define slots, it will behave like a regular class with dict, losing the memory optimization.
If you need weak references with slots, you must explicitly include ‘weakref’ in the slots declaration. This example shows how.
weakref_slots.py
import weakref
class WeakRefable: slots = (’weakref’, ‘data’)
def __init__(self, data):
self.data = data
obj = WeakRefable(42) r = weakref.ref(obj) print(r().data) # 42
By including ‘weakref’ in slots, we enable weak reference support while still maintaining memory optimization. Without it, weakref.ref() would raise TypeError.
This is necessary because slots replaces the default mechanism that normally provides weak reference support. The slot must be explicitly added.
slots works well with properties, allowing controlled attribute access while still benefiting from memory optimization. Here’s an example.
slots_properties.py
class Temperature: slots = (’_celsius’,)
def __init__(self, celsius):
self._celsius = celsius
@property
def celsius(self):
return self._celsius
@property
def fahrenheit(self):
return (self._celsius * 9/5) + 32
temp = Temperature(25) print(temp.fahrenheit) # 77.0
This Temperature class uses slots for memory efficiency while providing property-based access to temperature values. The internal _celsius attribute is stored in the slots structure.
Properties don’t need to be listed in slots as they’re class attributes, not instance attributes. Only data attributes need slots entries.
Use for memory-critical applications: When creating many instances
Document slot attributes: Clearly document all allowed attributes
Consider inheritance carefully: Child classes need their own slots
Add weakref if needed: For weak reference support
Don’t use prematurely: Only optimize after profiling shows need
My name is Jan Bodnar, and I am a passionate programmer with extensive programming experience. I have been writing programming articles since 2007. To date, I have authored over 1,400 articles and 8 e-books. I possess more than ten years of experience in teaching programming.
List all Python tutorials.