Python __slots__ Method

Complete guide to Python's __slots__ method covering memory optimization, attribute restriction, and performance benefits.

Python __slots__ Method

Python slots Method

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.

Basic Definitions

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.

Basic slots Implementation

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

p.z = 5 # Raises AttributeError

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.

Memory Optimization with slots

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.

Inheritance with slots

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)

obj.c = 3 # Raises AttributeError

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.

Using slots with Weak References

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.

Combining slots with Properties

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

temp._celsius = 30 # Works (but underscore indicates “private”)

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.

Best Practices

  • 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

Source References

Author

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.

ad ad