Skip to content
Foxipa

Suggest an edit

Tell us what should be corrected, clarified, or improved. Submission will be connected to Foxipa’s contribution service later.

No information is sent anywhere yet. Your suggestion is only prepared in your browser.

Learning

Python __slots__ and Instance Storage

Learn how Python __slots__ declares instance attributes, controls dynamic attributes, and changes instance storage.

Levels: Advanced ~20 min read

Advanced

The __slots__ class attribute lets a class explicitly declare the instance attributes it uses. Python then creates slot descriptors for those names instead of automatically giving each instance a normal __dict__ for arbitrary attributes.

Declare the instance attributes a class expects

Set __slots__ to a string or an iterable of attribute names. Those names become the declared instance attributes for the class.

python
1
2
3
4
5
6
7
8
9
class User:
    __slots__ = ("name", "active")

    def __init__(self, name):
        self.name = name
        self.active = True

user = User("Maya")
print(user.name, user.active)

The class declares name and active as its instance storage slots.

Undeclared instance attributes are rejected

When an instance does not have a __dict__, assigning a name that is not represented by a slot raises AttributeError. This makes the set of allowed instance attributes explicit.

python
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
class Device:
    __slots__ = ("name",)

    def __init__(self, name):
        self.name = name

device = Device("sensor")

try:
    device.location = "lab"
except AttributeError:
    print("location is not a declared slot")

The undeclared location attribute cannot be added to this slotted instance.

__slots__ does not make slot values immutable

A slot controls where an attribute is stored; it does not make that attribute read-only. A declared slot can still be assigned a new value normally.

python
1
2
3
4
5
6
7
8
9
class Score:
    __slots__ = ("value",)

    def __init__(self, value):
        self.value = value

score = Score(10)
score.value = 20
print(score.value)

The value slot can be reassigned just like an ordinary instance attribute.

Slotted instances do not get __dict__ automatically

A class using only named slots does not automatically provide each instance with an instance dictionary. Code that needs arbitrary instance attributes cannot use that behavior unless __dict__ is explicitly included.

python
1
2
3
4
5
6
7
8
9
class Point:
    __slots__ = ("x", "y")

    def __init__(self, x, y):
        self.x = x
        self.y = y

point = Point(2, 3)
print(hasattr(point, "__dict__"))

Without a __dict__ slot, the instance has no ordinary instance dictionary.

Keep dynamic attributes by declaring __dict__

You can include __dict__ in __slots__ when the class needs both declared slots and additional dynamic attributes. Those extra attributes are then stored in the instance dictionary.

python
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
class Flexible:
    __slots__ = ("name", "__dict__")

    def __init__(self, name):
        self.name = name

item = Flexible("box")
item.color = "blue"
print(item.color)
print(item.__dict__)

The name slot is declared, while __dict__ allows an additional color attribute.

Inheritance changes how slots behave

Slots declared by a parent are available to child instances. But a child class derived from an unslotted parent still has the parent’s instance dictionary unless the overall inheritance design removes it. A child that defines its own slots should declare only its additional slots.

python
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
class Base:
    pass

class Child(Base):
    __slots__ = ("name",)

child = Child()
child.name = "Ada"
child.extra = 42
print(child.extra)

Because Base is unslotted, Child instances still have a __dict__ and can receive extra attributes.

python
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
class BaseSlots:
    __slots__ = ("base",)

    def __init__(self):
        self.base = 1

class ChildSlots(BaseSlots):
    __slots__ = ("extra",)

child = ChildSlots()
child.extra = 2
print(child.base, child.extra)
print(hasattr(child, "__dict__"))

A fully slotted hierarchy can declare additional storage at each level without creating an instance dictionary.

A slot does not create a default value

Declaring a slot reserves the attribute; it does not automatically assign a value to the instance. Reading a slot before something stores a value in it raises AttributeError.

python
1
2
3
4
5
6
7
8
9
class Reading:
    __slots__ = ("value",)

reading = Reading()

try:
    print(reading.value)
except AttributeError:
    print("value has not been assigned")

The value slot exists as a declared attribute, but this instance has not assigned a value yet.

Why use __slots__?

Use __slots__ when a class has a known set of instance attributes and you want to make that layout explicit. The official data model notes that slots can save space and can improve attribute lookup speed, but these are implementation-dependent performance considerations rather than a reason to use slots everywhere.

Important boundaries

__slots__ is not a privacy feature, does not make values immutable, and does not by itself validate attribute values. It is also compatible with descriptors: Python implements each named slot at the class level with a descriptor that manages access to the corresponding stored value.

Key takeaways

  • Use __slots__ to explicitly declare the instance attributes a class supports.
  • A class with named slots does not automatically give instances a __dict__.
  • Slot values remain assignable; __slots__ does not make attributes read-only.
  • Add __dict__ to __slots__ only when dynamic instance attributes are intentionally needed.
  • Inheritance matters: an unslotted parent can provide a child instance with a __dict__.
Was this page helpful?

Mark this learning resource complete to track your learning progress.