How and when to use __slots__ in python
originally posted at https://www.aabidsofi.com/posts/usage-of-slots-in-python/ ( for better readabilty of code check here )
Each python object has a _dict_ attribute which is a dictionary containing all other attributes. E.g. when you type self.attr python is actually doing self.dict[‘attr’].
As you can imagine using a dictionary to store attribute takes some extra space & time for accessing it.
What if you already knew which attributes your class is going to have . Then using _dict_ to store attributes doesn’t seem to be a good idea as we don’t need the dynamic nature of dicts .
This is where slots come to rescue .
What Are Slots In Python
_slots_ is a class variable which allows us declare the attributes of a class explicitly and denying the creation of _dict_ and _weakref_ for object instances .
The expected attributes can be assigned to _slots_ as a string, iterable, or sequence of strings with variable names used by instance .
Space saved by not having a _dict_ can be significant . Slots also improve the attribute lookup speed .
Usage Of Slots
Python utilises a considerably more compact internal representation for instances when you define _slots_. Instead of a dictionary, each instance is created around a small fixed-sized array, similar to a tuple or list.
As a result of using slots, you can no longer add new attributes to instances; you are limited to the attribute names given in the _slots_ specifier.( You can get around this by adding _dict_ to the _slot_ . The dict will only initialized when a dynamic attribute is added ) .
Example showing usage of slots :
# A email class with out using slotsclass Email :
def __init__(self,subject,to,message) :
self.subject = subject
self.message = message
self.to = to
class EmailWithSlots : __slots__ = ('subject','to','message') def __init__(self,subject,to,message) :
self.subject = subject
self.message = message
self.to = to
email = EmailWithSlots('test','me@gmail.com','testing slots')email.subject
# >> testemail.__dict__ # cant access __dict__ because its not created
# AttributeError Traceback (most recent call last)
# <ipython-input-40-b95667a7fb92> in <module>
# ----> 1 email.__dict__
#
#AttributeError: 'EmailWithSlots' object has no attribute '__dict__'email.from = "aabid@gmail.com" # cant add an atribute that not in __slots__# ---------------------------------------------------------------------------
# AttributeError Traceback (most recent call last)
# <ipython-input-42-87651e4df821> in <module>
# ----> email.from = "aabid@gmail.com"
#
#AttributeError: 'EmailWithSlots' object has no attribute 'from'
Pros And Cons Of Slots
Pros
- using _slots_ has faster attribute access .
- _slots_ reduces memory usage
Cons
- Fixed attributes ( You can get around this by adding _dict_ to the _slots_ . The dict will only initialized when a dynamic attribute is added )
- _slots_ are implemented at the class level by creating descriptors for each variable name. As a result, class attributes cannot be used to set default values for instance variables defined by _slots_; otherwise, the class attribute would overwrite the descriptor assignment.
Conclusion :
_slots_ allow us to explicitly state which instance variables to expect in the object
Which gives us following benefits
- Faster Attribute Access
- Saves Memory
A Typical Use Case
For classes that primarily serve as simple data structures, you can often greatly reduce the memory footprint of instances by adding the _slots_ attribute to the class definition.
When Slots Is A Bad Idea .
- Avoid them when you want to perform _class_ assignment with another class that doesn’t have them (and you can’t add them) unless the slot layouts are identical. (I am very interested in learning who is doing this and why.)
- Avoid them if you want to subclass variable length builtins like long, tuple, or str, and you want to add attributes to them.
- Avoid them if you insist on providing default values via class attributes for instance variables.
Thanks , for reading till end Happy coding ..