__slots__ and Memory Optimization
Use __slots__ to reduce per-instance memory overhead.
__slots__ and Memory Optimization is a free Python Academy lesson on CoddyKit. This is lesson 4 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the Python Academy learning path, and your progress syncs across the web and the CoddyKit app. The Python Academy course includes 4 lessons in total.
The Default __dict__ Overhead
By default every Python instance stores attributes in a __dict__ dictionary, which has significant memory overhead — typically 200-400 bytes per instance.
import sys
class Point:
def __init__(self, x, y): self.x, self.y = x, y
p = Point(1, 2)
print(sys.getsizeof(p.__dict__)) # ~200 bytesDeclaring __slots__
Define __slots__ as a sequence of attribute names. Python allocates a fixed-size array instead of a dict, saving memory.
class SlottedPoint:
__slots__ = ("x", "y")
def __init__(self, x, y):
self.x = x
self.y = y
p = SlottedPoint(1, 2)
print(p.x, p.y) # 1 2
# p.z = 3 # AttributeError: no __dict__Memory Savings
With __slots__, each instance typically saves 30-50% memory compared to a dict-based instance — significant when creating millions of objects.
import sys
class Reg:
def __init__(self, x, y): self.x, self.y = x, y
class Slotted:
__slots__ = ("x","y")
def __init__(self, x, y): self.x, self.y = x, y
print(sys.getsizeof(Reg(1,2))) # ~56 bytes + ~200 dict
print(sys.getsizeof(Slotted(1,2))) # ~56 bytes (no dict)No __dict__ by Default
A slotted class has no __dict__, so you cannot add arbitrary attributes after creation.
class Config:
__slots__ = ("host", "port")
def __init__(self, h, p): self.host, self.port = h, p
c = Config("localhost", 8080)
# c.debug = True # AttributeError
print(hasattr(c, "__dict__")) # FalseKeeping __dict__ with __slots__
Include "__dict__" in __slots__ to retain a per-instance dict while still pre-declaring common attributes as slots.
class Hybrid:
__slots__ = ("x", "__dict__")
def __init__(self, x):
self.x = x
h = Hybrid(1)
h.extra = "dynamic" # allowed
print(h.extra)__weakref__ in __slots__
Slotted classes lose weak-reference support. Add "__weakref__" to __slots__ to re-enable it.
import weakref
class Node:
__slots__ = ("value", "__weakref__")
def __init__(self, v): self.value = v
n = Node(42)
ref = weakref.ref(n)
print(ref()) # <Node object>Inheritance and __slots__
If a parent class does not use __slots__, the child still gets a __dict__. For full savings, the entire hierarchy must define __slots__.
class Base:
__slots__ = ("x",)
class Child(Base):
__slots__ = ("y",) # no __dict__
class WithoutSlots(Base):
pass # gets __dict__ from objectBenchmarking Memory
Use tracemalloc or pympler to measure actual memory usage before and after adding __slots__.
import tracemalloc
tracemalloc.start()
points = [SlottedPoint(i, i) for i in range(100_000)]
current, peak = tracemalloc.get_traced_memory()
tracemalloc.stop()
print(f"Peak: {peak/1024/1024:.1f} MB")__slots__ and Pickling
Slotted objects can be pickled if you define __getstate__ and __setstate__ or use the default pickle protocol which handles slots automatically from Python 3.
import pickle
class Point:
__slots__ = ("x", "y")
def __init__(self, x, y): self.x, self.y = x, y
p = Point(3, 4)
data = pickle.dumps(p)
p2 = pickle.loads(data)
print(p2.x, p2.y) # 3 4dataclasses with __slots__ — Python 3.10+
Pass slots=True to @dataclass to automatically generate __slots__.
from dataclasses import dataclass
@dataclass(slots=True)
class Vector:
x: float
y: float
v = Vector(1.0, 2.0)
print(v.x, v.y) # 1.0 2.0
print(hasattr(v, "__dict__")) # FalseWhen to Use __slots__
Use __slots__ when: creating millions of instances, memory is constrained, or attribute-access speed is critical. Skip it for general-purpose classes where flexibility matters more.
# Good candidates:
# - Nodes in a large graph or tree
# - Records in a large dataset
# - High-frequency event objects
# Bad candidates:
# - Configuration objects added to ad-hoc
# - Classes that mix-in dynamic attributesQuick Check
What happens when you try to set an attribute not listed in __slots__ on a slotted instance?
Recap
__slots__ replaces the per-instance __dict__ with a fixed array, saving 30-50% memory. Include "__dict__" or "__weakref__" if you need them. The entire inheritance chain must use __slots__ for full savings. In Python 3.10+ use @dataclass(slots=True).
Learn Python with an AI tutor — free
Write and run real code in your browser, get instant help from a 24/7 AI tutor, and pick up where you left off on the web or in the app.
- Courses
- 76
- Lessons
- 320
Frequently Asked Questions
Is the “__slots__ and Memory Optimization” lesson free?
Yes — the full text of “__slots__ and Memory Optimization” is free to read here on the web. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the Python Academy course, upgrade to CoddyKit PRO. The Python Academy course includes 4 lessons in total.
What will I learn in “__slots__ and Memory Optimization”?
Use __slots__ to reduce per-instance memory overhead. You practise Python Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.
Do I need any experience to start Python Academy?
No prior experience is required. Python Academy on CoddyKit is structured for beginners through advanced learners, so you can start here or from the beginning and move at your own pace. This is lesson 4 of 4.
How long does the “__slots__ and Memory Optimization” lesson take?
Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.
Can I write and run code in this Python Academy lesson?
Yes. Every Python Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.
All lessons in this course
- How Python Classes Are Created
- Writing Custom Metaclasses
- Descriptors: __get__, __set__, __delete__
- __slots__ and Memory Optimization