I’ll help you understand **slots in Python**, which are a memory optimization feature for classes.
## What are Slots?
Slots (`__slots__`) allow you to explicitly declare data members (attributes) in a class and prevent the creation of `__dict__` and `__weakref__` for instances, saving memory.

## Basic Example
“`python
class Person:
__slots__ = (‘name’, ‘age’)
def __init__(self, name, age):
self.name = name
self.age = age
# Usage
p = Person(“Alice”, 30)
print(p.name) # Alice
print(p.age) # 30
# This will raise AttributeError because ‘email’ is not in __slots__
# p.email = “[email protected]”
“`
## Benefits of Using Slots
### 1. **Memory Efficiency**
“`python
import sys
class WithoutSlots:
def __init__(self, x, y):
self.x = x
self.y = y
class WithSlots:
__slots__ = (‘x’, ‘y’)
def __init__(self, x, y):
self.x = x
self.y = y
obj1 = WithoutSlots(1, 2)
obj2 = WithSlots(1, 2)
print(f”Without slots: {sys.getsizeof(obj1) + sys.getsizeof(obj1.__dict__)} bytes”)
print(f”With slots: {sys.getsizeof(obj2)} bytes”)
“`
### 2. **Faster Attribute Access**
Slots use a more efficient mechanism for attribute lookup.
## Important Considerations
### Inheritance with Slots
“`python
class Base:
__slots__ = (‘x’,)
class Derived(Base):
__slots__ = (‘y’,) # Adds ‘y’, inherits ‘x’ from Base
def __init__(self, x, y):
self.x = x
self.y = y
d = Derived(10, 20)
print(d.x, d.y) # 10 20
“`
### Multiple Inheritance with Slots
“`python
class A:
__slots__ = (‘a’,)
class B:
__slots__ = (‘b’,)
class C(A, B):
__slots__ = (‘c’,) # Must redeclare all parent slots
def __init__(self, a, b, c):
self.a = a
self.b = b
self.c = c
“`
## When to Use Slots
✅ **Use slots when:**
– Creating many instances of a class (memory optimization)
– Class has a fixed set of attributes
– Performance is critical
– Working with data-oriented classes
❌ **Avoid slots when:**
– Need dynamic attribute assignment
– Using multiple inheritance with conflicting slots
– Need `__dict__` for serialization or other purposes
– Using mixins or complex inheritance hierarchies
## Complete Example with Properties
“`python
class Employee:
__slots__ = (‘_name’, ‘_salary’, ‘_id’)
def __init__(self, name, salary, emp_id):
self._name = name
self._salary = salary
self._id = emp_id
@property
def name(self):
return self._name
@property
def salary(self):
return self._salary
@salary.setter
def salary(self, value):
if value >= 0:
self._salary = value
else:
raise ValueError(“Salary cannot be negative”)
# Usage
emp = Employee(“John”, 50000, “E001”)
print(emp.name) # John
emp.salary = 55000 # Works
# emp.title = “Manager” # Error: ‘Employee’ object has no attribute ‘title’
“`
## Common Pitfalls
“`python
class Problematic:
__slots__ = (‘x’,)
def __init__(self):
self.x = 10
# This won’t work – can’t assign new attributes
def add_attribute(self):
# self.y = 20 # AttributeError
pass

# Solution: Use a different approach if you need flexibility
class Flexible:
__slots__ = (‘x’, ‘y’, ‘z’) # Define all possible attributes
def __init__(self):
self.x = 10
# y and z can be set later if needed
“`
## Performance Comparison
“`python
import timeit
class Regular:
def __init__(self, x, y):
self.x = x
self.y = y
class Slotted:
__slots__ = (‘x’, ‘y’)
def __init__(self, x, y):
self.x = x
self.y = y
# Attribute access speed
regular_time = timeit.timeit(‘obj.x’,
setup=’obj = Regular(1, 2)’,
globals=globals())
slotted_time = timeit.timeit(‘obj.x’,
setup=’obj = Slotted(1, 2)’,
globals=globals())
print(f”Regular access: {regular_time:.6f}s”)
print(f”Slotted access: {slotted_time:.6f}s”)
“`
**Slots are a powerful optimization tool**, but use them judiciously. They’re excellent for data-heavy applications where you create many instances of a class with a fixed structure, but they reduce flexibility.
