Dynamic programming languages are popular when it comes to prototyping thanks to REPL and ease with which most of the things, including class schema, can be changed at runtime. But we all know that everything has a cost and this dynamism is not an exception. For example, for a simple class below
the name attribute value is stored in a __dict__ under the hood
This means that the attribute value accesses result in dictionary lookups and dictionary instance takes significantly more memory than a string.
But what if we don’t need this extra flexibility? Well, that’s where slots come into picture. We can use slots to define all attributes in advance
In this case, instead of using __dict__ for attribute lookups, a pointer to a name attribute will be stored directly in the User2 instance, which results in reduced memory footprint
since __dict__ and __weakref__ attributes are gone and name attribute is stored directly in the u2 instance
Great, looks like we’ve managed to reduce memory usage, but what about performance? Does it even matter? Let’s find out.
So looks like we also get ~16% boost for attribute lookups for free. The only disadvantage is a somewhat ugly syntax and it would be great to use typing.NamedTuple that serves the same purpose as good old collections.namedtuple but with a much better aesthetics
Unfortunately even though it doesn’t use __dict__, it also does not use __slots__ and as such has performance similar to dict based User1
So to get the best possible memory and performance characteristics, explicit usage of slots is a small price to pay and as such should be considered for compute and memory intensive applications, although in such case usage of other programming languages may be a better idea :)