tags:

views:

1758

answers:

4

In Python, when would I want to use __slots__ and when would I want to avoid it?

+11  A: 

You would want to use __slots__ if you are going to instantiate a lot (hundreds, thousands) of objects of the same class. __slots__ only exists as a memory optimization tool.

It's highly discouraged to use __slots__ for constraining attribute creation, and in general you want to avoid it because it breaks pickle, along with some other introspection features of python.

Ryan
+15  A: 

Quoting Jacob Hallen:

*"The proper use of __slots__ is to save space in objects. Instead of having a dynamic dict that allows adding attributes to objects at anytime, there is a static structure which does not allow additions after creation. This saves the overhead of one dict for every object that uses slots. While this is sometimes a useful optimisation, it would be completely unnecessary if the Python interpreter was dynamic enough so that it would only require the dict when there actually were additions to the object.

"Unfortunately there is a side effect to slots. They change the behavior of the objects that have slots in a way that can be abused by control freaks and static typing weenies. This is bad, because the control freaks should be abusing the metaclasses and the static typing weenies should be abusing decorators, since in Python,there should be only one obvious way of doing something.

"Making CPython smart enough to handle saving space without __slots__ is a a major undertaking, which is probably why it is not on the list of changes for P3k (yet)."*

Jeff Bauer
@Jeff - thanks for the excellent contribution. I've always wondered about `__slots__` too.
orokusaki
+2  A: 

You have -- essentially -- no use for __slots__.

The time when you think you might need __slots__, you actually want to use Lightweght or Flyweight design patterns. These are cases when you no longer want to use purely Python objects. Instead, you want a Python object-like wrapper around an array, struct or numpy array.

class Flyweight( object ):
    def get( self, theData, index ):
        return theData[index]
    def set( self, theData, index, value ):
        theData[index]= value

The class-like wrapper has no attributes -- it just provides methods that act on the underlying data. The methods can be reduced to class methods. Indeed, it could be reduced to just functions operating on the underlying array of data.

S.Lott
What has Flyweight to do with __slots__?
oefe
@oefe: I certainly don't get your question. I can quote my answer, if it helps "when you think you might need __slots__, you actually want to use ... Flyweight design pattern". That's what Flyweight has to do with __slots__. Do you have a more specific question?
S.Lott
@oefe: Flyweight and `__slots__` are both optimization techniques to save memory. `__slots__` shows benefits when you have many many objects as well as Flyweight design pattern. The both solve the same problem.
J.F. Sebastian
+2  A: 

Each python object has a __dict__ atttribute 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.

However, when you use 'slots', any object created for that class won't have a 'dict' attribute. Instead, all attribute access is done directly via pointers.

So if want a C style structure rather than a full fledged class you can use __slots__ for compacting size of the objects & reducing attribute access time. A good example is a Point class containing attributes x & y. If you are going to have a lot of points, you can try using __slots__ in order to conserve some memory.

Suraj Barkale