[Python-Dev] Re: __slots__ and default values

Raymond Hettinger python@rcn.com
Tue, 13 May 2003 21:12:03 -0400


> Aahz replies:
> > Why not do the initializing in __init__?
> 
> Michael:
> I presume that Raymond's concern was not that there wouldn't be
> a way to do initialization, but that this would become a new c.l.p
> FAQ and point of confusion for newbies. Unfortunately, I fear
> that it will. 

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).

> 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.

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?

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.

> 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.

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


> 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. 


Raymond Hettinger