inheritance, multiple inheritance and the weaklist and instance dictionaries

Carl Banks pavlovevidence at gmail.com
Wed Feb 9 16:58:12 EST 2011


On Feb 9, 1:14 pm, Rouslan Korneychuk <rousl... at msn.com> wrote:
> On 02/09/2011 02:42 PM, Carl Banks wrote:
> > This is the only case I can think of where the
> > layout conflict would be caused by a type setting tp_dictoffset.
>
> No, actually I have code that is roughly equivalent to the following
> pseudocode:
>
> class _internal_class(object):
>      __slots__ = ()
>
> class BaseA(_internal_class):
>      __slots__ = (some_data,...,__weaklist__,__dict__)
>
> class BaseB(BaseA):
>      __slots__ = (some_data,...,__weaklist__,__dict__)
>
> class BaseC(_internal_class):
>      __slots__ = (some_other_data,...,__weaklist__,__dict__)
>
> class Derived(BaseB,BaseC):
>      __slots__ = (combined_data,...,__weaklist__,__dict__)

Ah, ok.  So BaseA sticks weaklist and dict into a certain layout
location.  BaseB gets the same location because it has the same
layout.
BaseC sticks weaklist and dict into a different location.  Derived
then can't reconcile it because dict and weakref are in different
locations.

Again, for the reasons I mentioned the layouts conflict even if you
set tp_weakreflist and tp_dictoffset.


> Before adding the weaklist and instance dicts, this all worked fine.
> _internal_class was necessary to prevent the "lay-out conflict" error.

That actually seems like an error to me.  It should signal a conflict
if bases have different layout sizes from their own base, and one
isn't a base of the other, which wouldn't be the case here.

"some_data" a proper subset of "some_other_data", right?  (If it isn't
you have worse problems than dict and weakreflist.)  A more natural
way to handle this situation would be to place common slots in the
internal_class.

But we'll just accept it for now.


> But when I added them to every class except _internal_class, I got the
> error. I tried adding the dicts to _internal_class and it worked again.
> (The classes are set up like this because the code is from my unit-test
> code.)

Don't set tp_dictoffset and tp_weakrefoffset in any of the bases.  Set
them only in Derived.  If you need to instantiate a Base, make a
trivial dervied class for it.



Carl Banks



More information about the Python-list mailing list