There is a lesser-known feature of Python classes: class attribute
Normally, each instance object
x of class
C has a dictionary
x.__dict__ which let you bind arbitrary attributes on
x. When a class
has a class attribute
__slots__ defined (a tuple of strings), an instance
x of class
C has no
x.__dict__, and any attempt to bind on
any attribute whose name is not in
C.__slots__ raises an exception.
__slots__ attribute reduces memory consumption for instance objects. The saving is a only few tens of bytes per instance, but significant
when the number of instances grows to millions/tens of thousands.
Let’s do some experiments with iPython. The snippets below assume
memory_profiler is installed (
pip install memory_profiler).
First let’s profile some code in Python 2.7 (2.7.12) in iPython.
The result speaks for itself; using
__slots__ attributes does save A LOT of memory for large amount of simple objects,
at least in Python 2.7. Now let’s see if this still holds for Python 3 (3.6.1).
According to the result from Python 3.6, it looks like
__slots__ still saves memory, but not as dramatic as in Python 2; and overall Python 3.6 seems to use
much less memory than Python 2.7 for instances without
__slots__. Some more discussions on StackOverflow can be found here for deeper understanding.
To conclude, using
__slots__ does save memory usage, and the main saving comes from avoiding using
__dict__ in instances objects. And, since Python 3.3,
such savings is not so impressive anymore due to an improvement in the implementation of attribute dictionaries (PEP0412, and see Python Tutorial on Slots).