[Python-Dev] Re: __slots__ and default values

Guido van Rossum guido@python.org
Tue, 13 May 2003 21:38:27 -0400


> Yes.  Since it "works" with classic classes and unslotted newstyle
> classes, it isn't terribly unreasonable to believe it would work 
> with __slots__.  Further, there is no reason it couldn't work (either 
> through an autoinit upon instance creation or through a default 
> entry that references the class variable).

Really?  The metaclass would have to copy the initializers to a
safekeeping place, because they compete with the slot descriptors.
Don't forget that when you write __slots__ = ['a', 'b', 'c'],
descriptors named a, b and c are inserted into the class dict by the
metaclass.  And then the metaclass would have to add a hidden
initializer that initializes the slot.  Very messy...

> > Michael:
> > Already I am seeing that people are "discovering"
> > class variables as a sort of "initialized instance variable"
> > instead of using __init__ as they "ought" to. Of course, it's NOT
> > an initialized instance variable, but newbies stumble across it
> > and seem to prefer it to using __init__.
> 
> Perhaps I skipped school the day they taught that was bad, but
> it seems perfectly reasonable to me and I'm sure it is a common
> practice.  I even find it to be clearer and more maintainable than
> using __init__.  The only downside I see is that self.classvar += 1
> reads from and writes to a different place.

It's also a bad idea for initializers that aren't immutable, because
the initial values are shared between all instances (another example
of the "aliasing" problem, also known from default argument values).

> So, a reworded version of my question is "why not?".  What is
> the downside of providing behavior that is similar to non-slotted
> classes?  What is gained by these blocking an assignment and
> reporting a read-only error?

It's not like I did any work to prevent what you want from working.
Rather, what you seem to want would be hard to implement (see above).

> When I find an existing class can be made lighter by using __slots__,
> it would be nice to transform it with a single line.  From:
> 
> class Tree(object):
>     left = None
>     right = None
>     def __init__(self, value):
>         self.value = value
> 
> adding only one line:
>     __slots__ = ('left', 'right', 'value')
> 
> It would be a bummer to also have to move the left/right = None
> into __init__ and transform them into self.left = self.right = None.

Maybe I should remove slots from the language?  <0.5 wink> They seem
to be the most widely misunderstood feature of Python 2.2.  If you
don't understand how they work, please don't use them.

> > Duncan Booth:
> > The following works, but I can't remember whether you're supposed to be 
> > able to use a dict in __slots__ or if it just happens to be allowed:
> >
> > >>> class Pane(object):
> > __slots__ = { 'background': 'black', 'foreground': 'white',
> >       'size': (80, 25) }
> > def __init__(self):
> > for k, v in self.__slots__.iteritems():
> > setattr(self, k, v)
> 
> __slots__ accepts any iterable.  So, yes, you're allowed
> eventhough that particular use was not intended.

This loophole was intentionally left for people to find a good use for.

> There are several possible workarounds including metaclasses.
> My question is why there needs to be a workaround at all.

I hope that has been answered by now.

> > Thomas Heller:
> > Unrelated to *this* topic, but Andrew's "What's new in Python 2.2" still
> > presents __slots__ as a way to constrain the instance variables:
> > 
> > A new-style class can define a class attribute named __slots__ to
> >  constrain the list of legal attribute names.
> 
> Though I think of __slots__ as a way to make lighter weight instances,
> constraining instance variables is also one of its functions. 

Not true.  That is at best an unintended side effect of slots.  And
there's nothing against having __slots__ include __dict__, so your
instance has a __dict__ as well as slots.

--Guido van Rossum (home page: http://www.python.org/~guido/)