On Sat, May 12, 2012 at 9:10 AM, Ethan Furman <et...@stoneleaf.us> wrote: > > Firstly, __slots__ is a tuple.
I object: conceptually, the "slots" of a class are set in stone, but the `__slots__` attribute of a class object is just an attribute, and any iterable (as long as it yields valid identifier names) can be used when the `__slots__` magic is invoked in the class definition. FWIW, all the ordinary examples I've seen use a list, although a tuple arguably makes more sense. Observe: >>> class Evil(object): ... __slots__ = ('a%s' % a for a in range(10)) ... >>> Evil().__slots__ <generator object <genexpr> at 0x01EDFAA8> >>> list(Evil().__slots__) [] # the generator was consumed by the metaclass during class creation >>> dir(Evil()) ['__class__', '__delattr__', '__doc__', '__format__', '__getattribute__', '__has h__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__rep r__', '__setattr__', '__sizeof__', '__slots__', '__str__', '__subclasshook__', ' a0', 'a1', 'a2', 'a3', 'a4', 'a5', 'a6', 'a7', 'a8', 'a9'] # yep, the expected attributes are there, and can be set. >>> Evil.__slots__ = 42 # no exception > > Secondly, this is bad advice. __slots__ is there as a memory optimization > for classes that will have thousands of instances and do not need the > ability to have arbitrary attributes added after creation. I did explicitly indicate the latter part. > __slots__ is an > advanced feature, and as such is easier to get wrong. It is *not* there to > make __str__ nor __repr__ easier to write. Of course not, but it seems to me that it serves well in this particular case. >>>> class Test1(object): > ... __slots__ = ('item', 'size') > ... desc = 'class-only attribute' > ... > >>>> t1 = Test1() >>>> t1.desc = 'read-only attribute' # fails because 'desc' is > # not in __slots__ Well, sure; expecting to modify a class attribute via an instance is a bit naughty anyway. >>>> print t1.item # fails because 'item' was > # not set Well, yes, that's what `__init__` is for; the same line would fail without `__slots__` and for the same reason. Arguably, this is a gotcha for people coming from C-like languages who are expecting `__slots__` to make the class behave as if it had a defined layout, but there isn't actually any more work involved here. >>>> class Test2(Test1): > ... def __init__(self, price): > ... self.price = price > ... >>>> t2 = Test2(7.99) # __slots__ not defined in > # subclass, optimizations lost Well, yes, but we aren't using it for the optimizations here! But I see your point; explicit is better than implicit, and our explicit purpose here is to have an explicit list of the attributes we're interested in for __str__/__repr__ - which could be any other named class attribute, without magic associated with it. That said, `__slots__` is as close to a canonical listing of instance-specific attributes as we have (`dir()` clearly won't cut it, as we don't want methods or other class-specific stuff). -- ~Zahlman {:> -- http://mail.python.org/mailman/listinfo/python-list