dynamism

Duncan Booth duncan at NOSPAMrcp.co.uk
Thu Sep 12 10:53:11 CEST 2002


steven_shaw at adc.com (Steven Shaw) wrote in
news:66715c02.0209111633.771aa9d3 at posting.google.com: 

> Thanks alot for your time on this.
It was fun!

> I hadn't read about the __slots__
> mechanism before. I feel that there must be something wrong, though,
> because the Old object layout is winning! Maybe the implementation is
> finding the index of the variable in the __slots__ array and then>
> using returning __values__[index] in order to implement the attribute 
> access. I made up the "__values__" array - there must be a values
> array somewhere. Array-based object layout amounts to the same thing
> as record-based-layout in Python because all primitives are the same
> size (right?). There needs to be a way for Python to remember the
> indexes... Hmmm. I think your test code doesn't allow the compiler to
> remember the indexes since it creates an instance anonymously (using
> klass).

It is quite hard working out from the code what happens, but basically when 
you define __slots__ it allocates space in the object to hold the actual 
data for each slot, and makes a copy of the __slots__ list. It also creates 
an object of type member_descriptor for each slot and stores it in the 
class dictionary under the name of the slot.

class C(object):
   __slots__ = ['a', 'b']
inst = C()

If you look at C.__dict__['a'] and C.__dict__['b'] they are 
member_descriptor objects. Accessing inst.a therefore will call 
C.a.__get__(inst, C) or C.a.__set__(inst, value). Each member_descriptor 
object knows the offset where its data is stored.

So you still have the overhead of a dictionary lookup for every __slot__ 
access (although Python dictionary lookup is pretty fast), and you have 
saved the overhead of a dictionary on every instance at the cost of an 
extra object in the class for each attribute. It is slower than ordinary 
attribute access because after the dictionary lookup instead of returning 
the value that was found you have to call one of its methods (although 
fortunately that doesn't involve another dictionary lookup, just a C call).

I hope this makes sense.

-- 
Duncan Booth                                            
duncan at rcp.co.uk int month(char
*p){return(124864/((p[0]+p[1]-p[2]&0x1f)+1)%12)["\5\x8\3" 
"\6\7\xb\1\x9\xa\2\0\4"];} // Who said my code was obscure? 



More information about the Python-list mailing list