[Python-Dev] perplexed by mro

Guido van Rossum guido@python.org
Thu, 03 Oct 2002 21:54:51 -0400


> > Now let's assume m is *also* overridden in a, so that y.m overrides
> > a.m overrides object.m.  Now if we searched b before y (naive algo),
> > it is arguably strange if the 'super' call chain went from y.m via b.m
> > to a.m.
> 
> I don't understand that. According to the diagram I just
> scribbled, the mro from the documented algorithm comes out as
> 
>   z, x, b, y, a, c, object
> 
> so the super chain would be b.m, y.m, a.m, object.m.

Sorry, I misread my own scribbled diagram.  That's indeed the correct
order using the naive algorithm.  And I now agree that this is a fine
call chain.

> (Which is *also* wrong according to my intuition, by the way --
> I would expect a super call inside b.m to go to object.m,
> and not depend on z's inheritance structure -- but that's a
> separate issue.)

No, the whole point here is that the most inherited class's MRO
(i.e. z) can insert things in a base class's MRO.  Have a look at the
explanation of the diamond diagram in
http://python.org/2.2.1/descrintro.html

> Anyway, why not just use the algorithm you said you were
> using in the docs -- i.e. traverse the inheritance hierarchy
> and build the mro afresh each time, rather than trying to
> merge the mro's of the superclasses.

I would still construct a linearized MRO out of it -- many places
benefit from having it as a list rather than having to recurse down
the inheritance lattice.  But I agree that the naive algorithm seems
to have some nice properties -- at the very least, it is easy to
explain. :-)

If Samuele agrees that the naive algorithm works better, I'll try to
make it so in 2.3.

> If it's an issue of which algorithm is the one that should
> be used, I vote for the documented one, because it's
> simple and easy to explain! If it leads to odd things
> happening in some cases, at least it's clear what odd
> things will happen and why -- as opposed to other odd
> things happening for mysterious reasons.

Yes.  Here's how this happened: I had read and implemented the book's
algorithm without really visualizing what it did in more complex
cases.  In the few cases that I cared about it worked fine.  When I
had to document it, I realized that the description in the book is
very complicated, and I tried to come up with a simpler description.
That's how I stumbled upon the naive algorithm -- at first I believed
that it was really the same thing, but later I found a counter-example
with an order disagreements, so I added that.

Now Samuele has found another counter-example that does not involve an
order disagreement.  It does have a somewhat strange smell to it, 
but I can't pinpoint the quality of that smell, and it certainly
doesn't have an order disagreement.

I've updated the descrintro.html page to acknowledge the problems.

--Guido van Rossum (home page: http://www.python.org/~guido/)