Skip to content
On this page

Using slots

Under normal circumstances, when we define a class and create an instance of that class, we can bind any attribute or method to the instance. This is the flexibility of dynamic languages. Let's start by defining a class:

python
class Student(object):
    pass

Next, let's try binding an attribute to the instance:

python
>>> s = Student()
>>> s.name = 'Michael'  # Dynamically bind an attribute to the instance
>>> print(s.name)
Michael

We can also bind a method to the instance:

python
>>> def set_age(self, age):  # Define a function as an instance method
...     self.age = age
...
>>> from types import MethodType
>>> s.set_age = MethodType(set_age, s)  # Bind the method to the instance
>>> s.set_age(25)  # Call the instance method
>>> s.age  # Check the result
25

However, the method bound to one instance does not affect other instances:

python
>>> s2 = Student()  # Create a new instance
>>> s2.set_age(25)  # Try to call the method
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'Student' object has no attribute 'set_age'

To bind a method to all instances, we can bind it to the class:

python
>>> def set_score(self, score):
...     self.score = score
...
>>> Student.set_score = set_score

After binding the method to the class, all instances can call it:

python
>>> s.set_score(100)
>>> s.score
100
>>> s2.set_score(99)
>>> s2.score
99

In general, the set_score method can be directly defined in the class, but dynamic binding allows us to add functionality to a class during runtime, which is difficult to achieve in static languages.

But what if we want to restrict the attributes that instances can have? For example, we only want to allow name and age attributes for Student instances.

To achieve this restriction, Python allows us to define a special __slots__ variable when defining a class. This variable limits the attributes that instances of the class can add:

python
class Student(object):
    __slots__ = ('name', 'age')  # Use a tuple to define the allowed attribute names

Now, let's test this:

python
>>> s = Student()  # Create a new instance
>>> s.name = 'Michael'  # Bind the 'name' attribute
>>> s.age = 25  # Bind the 'age' attribute
>>> s.score = 99  # Bind the 'score' attribute
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'Student' object has no attribute 'score'

Since score is not in __slots__, we cannot bind the score attribute. Attempting to do so will result in an AttributeError.

It's important to note that the attributes defined by __slots__ only affect instances of the current class and do not apply to subclasses:

python
>>> class GraduateStudent(Student):
...     pass
...
>>> g = GraduateStudent()
>>> g.score = 9999

Unless __slots__ is also defined in the subclass, in which case the allowed attributes for subclass instances will be the combination of the subclass's __slots__ and the parent class's __slots__.

Using slots has loaded