So you want to learn about Python’s __slots__?
To set the stage: what are slots in Python? Slots are a way to optimize memory usage by limiting the number and type of attributes that can be assigned to an instance. When you define __slots__ in your class, it replaces the instance dictionary with a fixed-length array of slot values. This means that instead of having to allocate space for every possible attribute (even if they’re not used), slots allow you to only use what you need.
Here’s an example: let’s say we have a class called Car, and we want it to have three attributes: make, model, and year. Normally, we would define the class like this:
# Define the class Car
class Car:
# Initialize the class with attributes make, model, and year
def __init__(self, make, model, year):
# Assign the make attribute to the input value for make
self.make = make
# Assign the model attribute to the input value for model
self.model = model
# Assign the year attribute to the input value for year
self.year = year
But if we want to use slots instead of a dictionary for our attributes, we can define the class like this:
# Defining a class named Car
class Car:
# Using slots instead of a dictionary for attributes
__slots__ = ('make', 'model', 'year')
# Initializing the class with attributes make, model, and year
def __init__(self, make, model, year):
# Assigning the make attribute to the input value for make
self.make = make
# Assigning the model attribute to the input value for model
self.model = model
# Assigning the year attribute to the input value for year
self.year = year
Notice that we added `__slots__ = (‘make’, ‘model’, ‘year’)` to the class definition. This tells Python to use slots instead of a dictionary for our attributes, and only allow us to set those three specific attributes (make, model, and year). If you try to add an attribute that isn’t in `__slots__`, you’ll get an error:
# Define a class called Car
class Car:
# Use __slots__ to specify the allowed attributes for the class
__slots__ = ('make', 'model', 'year')
# Define the __init__ method to initialize the attributes of the class
def __init__(self, make, model, year):
# Set the attributes using the values passed in during initialization
self.make = make
self.model = model
self.year = year
# Create an instance of the Car class with the specified attributes
car = Car('Ford', 'Mustang', 1964)
# Try to add a new attribute called 'color' to the car instance
car.color = 'red'
# Since 'color' is not specified in __slots__, an error will be raised
# This is because we are only allowed to set the attributes specified in __slots__
# and 'color' is not one of them
# The error message will indicate that the 'Car' object has no attribute 'color'
So, why would you want to use slots instead of a dictionary? Well, for one thing, it can save memory! If we have an instance with 10 attributes that are never used, those unused attributes still take up space in the instance dictionary. But if we define __slots__ and only allow three specific attributes, we’re saving memory by not allocating space for those unused attributes.
Another benefit of using slots is that it can improve performance! Since Python doesn’t have to look up attribute names in a dictionary every time you access or set an attribute, the code runs faster. This can be especially useful if you have a large number of instances with many attributes each.
By defining slots for your classes, you can optimize memory usage and improve performance. And who doesn’t love saving resources?