__slots_ and inheritance

Alex Martelli aleaxit at yahoo.com
Thu Apr 10 02:46:40 EDT 2003


Blair Hall wrote:
   ...
> In this case the attribute 'c' can be created. Perhaps a __slots__
> in the base class does not prevent attributes from being added
> to the derived class (I guess this is good). But,

Exactly.

> 
> # Third case: class A has no slots
> class A(object):
>      def __init__(self):
>          pass
> 
> class B(A):
>      __slots__ = ('z',)
>      def __init__(self):
>          A.__init__(self)
> 
> b = B()
> b.c = 3 # passes
> 
> in this case, although the class B has slots its base class
> does not. This seems to allow instances of B to ignore their
> own __slots__ requirements. This, to my mind, is a problem:
> it seems to require knowledge of the __slots__ in all
> base classes.
> 
> Can anyone steer me towards a better understanding of __slots__?

__slots__ is, essentially, an optimization (in terms of memory
consumption) intended for classes that are likely to be created 
in very large numbers: you give up the normal flexibility of
being able to add arbitrary attributes to an instance, and what
you gain in return is that you save one dictionary per instance
(dozens and dozens of bytes per instance -- that will, of course,
not be all that relevant unless the number of instances that are
around is at the very least in the tens of thousands).

If class X inherits class Y, and also has X.__slots__, then an
instance x of X can have any attribute that could be had by an
instance y of Y, PLUS attributes whose names are in X.__slots__.
This rule appears to me to be quite simple and regular.

Thus, the behavior in your "third case" should be obvious: if
the base class has no __slots__ then its instances can have any
attribute, and therefore so can instances of subclasses.

I suspect that any confusion may be caused by seeing __slots__
as something OTHER than an optimization -- for example, as a
way to reproduce the behavior of other languages where you
can, or must, specify possible attributes for every class.  It
isn't, really -- it's a memory-consumption optimization.

You complain that the simple rule for __slots__ "seems to
require knowledge of the __slots__ in all base classes", but
fail to specify what PURPOSE you think is going to be served
by meeting that "requirement" for knowledge.  Saving memory?
Sure, in order to save memory you do need to know all ways in
which memory could be consumed, at some level -- but in fact
all that you require is that every base class HAVE __slots__,
no knowledge of WHAT slots are used in every base class is at
all necessary in order for the purpose of __slots__ to be
accomplished - saving the per-instance dict otherwise required.


Alex





More information about the Python-list mailing list