method names in __slots__ ??

Rob Williscroft rtw at freenet.co.uk
Mon Dec 25 13:00:07 EST 2006


John Machin wrote in
news:1167067714.627280.76420 at n51g2000cwc.googlegroups.com in
comp.lang.python: 

> Rob Williscroft wrote:
>> John Machin wrote in news:1167008799.074885.250770@
>> 73g2000cwn.googlegroups.com in comp.lang.python:
>>
>> > Given a = Adder(),
>> >     a.tally = 0
>> > gets AttributeError: 'Adder' object attribute 'tally' is read-only
>> >     a.notinslots = 1
>> > gets AttributeError: 'Adder' object attribute 'notinslots' is
>> > read-only 
>> >
>> > So is there some magic class-fu going down here, or is this just a
>> > waste of memory space in the instances?
>> >
>>
>> Haven't you, with your 2 examples above, answered your own question ?
> 
> No.
> 
>>
>> Clearly from your example it doesn't make any difference if you add
>> a class attribute to the slots, one way or another its as if you
>> hadn't put it in there in the first place.
> 
> Clearly? Not so. It takes up memory. A list of 1 million Adder
> instances takes up about 68 Mb (Python 2.5 on Windows XP). With the
> method names removed from the __slots__, it takes only about 44 Mb.
> [For comparison: with no __slots__ at all, it takes about 180 Mb]
 
68 - 44 = 24
24 / 4 = 6

So thats 6 pointers for 5 methods, probably 5 pointers and and 4 bytes
round up to the nearest allocation unit.

So the slots in the instance are staying arround, even though they 
are no longer accesable (see below).

[snip]

> It would seem that the interpreter removes any names it finds as
>> class attribute names from the list it finds in __slots__ before it
>> creates the instance.
> 
> It doesn't seem so to me. If it did that, the memory usage would not
> increase.

It was a guess, and an incorrect guess, but thats why I quoted the 
docs below.

> 
>>
>> Of course if my guessing above isn't good enough, we could look at
>> the documentation:
>>
>>   http://docs.python.org/ref/slots.html#l2h-218
>>
>> __slots__ are implemented at the class level by creating descriptors
>> (3.4.2) for each variable name. As a result, class attributes cannot
>> be used to set default values for instance variables defined by
>> __slots__; otherwise, the class attribute would overwrite the
>> descriptor assignment. 
> 
> I have read that, before I posted. Asides:
> (1) It would be useful if it stated the empirically determined fact
> that the result is that the class attribute is thusly made read-only.
> (2) The second sentence is not a model of clarity.
> 
> In any  case I can't see how the paragraph gives any support for your
> next statement:
> 
>>
>> So its that the __slots__ assignment makes the descriptors and then
>> the subsiquent method defenitions and class attribute bindings remove
>> them. 
> 
> Errrmmm ... if the descriptors are removed, how is it that the
> behaviour is read-only?

The descriptors are part of the class object, they are removed 
when the class attributes are rebound, further rebinding of 
the class attributes will work fine:

  Adder.tally = 0

They are not assignable in the instance as the class descriptors 
that would have forwarded the assignment to the instances slots have 
been replaced.

The memory usage is higher because the slots in the instance are 
still there even though the descriptors that would allow them to 
be assigned have been removed.
 
Rob.
-- 
http://www.victim-prime.dsl.pipex.com/



More information about the Python-list mailing list