6

I'm using Python 3.7 and Django. I was reading about __slots__ . Evidently, __slots__ can be used to optimize memory allocation for a large number of those objects by listing all the object properties ahead of time.

class MyClass(object):
    __slots__ = ['name', 'identifier']
    def __init__(self, name, identifier):
        self.name = name
        self.identifier = identifier
        self.set_up()

My perhaps obvious question is why wouldn't we want to do this for all objects? Are there disadvantages for using __slots__?

Miguel Guthridge
  • 1,444
  • 10
  • 27
Dave
  • 15,639
  • 133
  • 442
  • 830
  • *Subjective (or context based) disadvantage:* dynamic attribute assignment doesn't work anymore as there is no `__dict__`. – heemayl Apr 19 '19 at 19:43
  • how is this not a dup of https://stackoverflow.com/q/472000/1358308 . lots and lots of very useful information – Sam Mason Apr 19 '19 at 20:17

1 Answers1

3

Fluent Python by Luciano Ramalho lists the following caveats

• You must remember to redeclare __slots__ in each subclass, since the inherited attribute is ignored by the interpreter.

• Instances will only be able to have the attributes listed in __slots__, unless you include __dict__ in __slots__ — but doing so may negate the memory savings.

• Instances cannot be targets of weak references unless you remember to include __weakref__ in __slots__.

Dušan Maďar
  • 9,269
  • 5
  • 49
  • 64
  • I'm a novice to Python so I may be grossly oversimplifying your answer, but from what I'm reading, it appears the only disadvantages are you have to add more code into your model. Am I reading you right? – Dave Apr 19 '19 at 20:22
  • Well, yes, grossly oversimplified. More code in subclasses (because `__slots__` from parent class are ignored) and dynamic attributes won't work (unless you do what's described in the second bullet point, which is kind of against what slots are for). – Dušan Maďar Apr 20 '19 at 07:03
  • 2
    @Dušan Maďar I don't understand your first point. I have just been experimenting (Python 3.7.3) and inheritance seems to work as I would expect it to. That is, an instance of a class without \_\_slots\_\_ but derived from a class with \_\_slots\_\_ will have a \_\_dict\_\_ so new members can be added dynamically but assigning to a variable declared in the parent class's \_\_slots\_\_ will not and an entry to the object's \_\_dict\_\_. – Chris Barry Jul 06 '19 at 10:43
  • @Dušan Maďar Your second point may qualify as a caveat but I would not call it a disadvantage. I think that this is how a class _should_ behave. If you need to add arbitrary attributes to individual instances then you should not be using a class. Apart from the memory saved by not creating a dictionary for each object this gives a useful check for typing errors. – Chris Barry Jul 06 '19 at 10:57
  • @ChrisBarry none of those points are mine. They are cited form `Fluent Python` (book). Please read the `first line` of the answer. – Dušan Maďar Jul 06 '19 at 11:02
  • 2
    @Dušan Maďar I apologise for conflating citation with endorsement. I assumed that as you were prepared to cite them you would be willing to defend them. I think that, except for exotic cases (how often do you use weak references?) every class declaration should be followed by \_\_slots\_\_. Its non-ubiquity, at least in the Python code I have looked at, suggests that I am wrong. I am still wondering why. – Chris Barry Jul 08 '19 at 14:16
  • "You must remember to redeclare `__slots__` in each subclass" is misleading. You should never redeclare any slots already declared by a superclass - doing so is undefined behavior, and in the current implementation, it causes instances to waste a bunch of extra memory. What you should do is declare any *new* slots introduced by a subclass, or set `__slots__ = ()` if there are no new slots. – user2357112 Aug 07 '22 at 16:02
  • (See the [notes](https://docs.python.org/3/reference/datamodel.html#notes-on-using-slots) in the Python docs.) – user2357112 Aug 07 '22 at 16:04