What is this __slots__
property for?
__slots__
.
What is it for and when should I use it?
What is this __slots__
property for?
__slots__
.
What is it for and when should I use it?
__slots__
is a very special attribute for classes - when it is not present, for each new instance of the class, Python creates a new dictionary, but it does not do that if the class sets __slots__
.
In Python I can write (Python 3 - in Python 2 it is necessary to inherit from object
):
class Ponto:
def __init__(self, x=0, y=0):
self.x = x
self.y = y
...
And this is what we normally know. We can, after instantiating a point, append a z
attribute to it:
p = Ponto()
p.z = 0
We know that, as a rule, it is not good practice, but the language accepts - and the idea of "consenting adults" from Python is that it avoids bad code that adds random attributes to objects of existing classes.
Now - most of the time you do not need to add new attributes to your points. And since each instance of Point has a dictionary to store its attributes, it turns out that an instance that would only use a little more than the space required for two objects of type float
to - maybe a ~ 80 bytes in total, also from an entire Python dictionary, even though it is zeroed - this is more than 200 bytes long.
When the class defines __slots__
, Python reserves space for the attributes defined in __slots__
in the class structure, and does not create a new dictionary for each instance.
That is, this:
class Ponto:
__slots__ = ('x', 'y')
def __init__(self, x=0, y=0):
self.x = x
self.y = y
will have the same functionality as the other, but a size of about 80 bytes, not ~ 300.
On the other hand, trying to create a new attribute results in an error:
AttributeError: 'Point' object has no attribute 'z'
On large systems that will have thousands of small objects, this can really make a difference. You can also imagine other ways to take advantage of this mechanism - for example: Python automatically creates class attributes ( dir(Ponto)
in the above class will show attributes x and y), etc ...
object
, int
, list
, etc ... have __slots__
defined - so you can not create new attributes in such instances - but if you inherit any such type, even if you leave the body of the class blank, you can create new attributes.
namespace = object()
namespace.x = 5
(Atribute Error)
class NS(object): pass
namespace = NS()
namespace.x = 5
(ok)
And it's also important to keep in mind that if you are going to create a class hierarchy and use __slots__
, each subclass will have to set __slots__
as well, otherwise, by default, Python creates __dict__
for class.