On Wednesday, November 15, 2017 at 5:32:00 PM UTC-5, Koos Zevenhoven wrote:
On Wed, Nov 15, 2017 at 11:49 PM, Neil Girdhar <miste...@gmail.com> wrote:
Sometimes I get MRO failures when defining classes.  For example, if

R < E, C
B < S, E
S < C
Z < B, R

Then Z cannot be instantiated because C precedes E in B and E precedes C in R.  The problem is that when the inheritance graph was topologically-sorted in B, the order was S, C, E.  It could just as easily have been S, E, C.  So, one solution is to add C explicitly to B's base class list, but this is annoying because B might not care about C (it's an implementation detail of S).  It also means that if the hierarchy changes, a lot of these added extra base classes need to be fixed.

I propose adding a magic member to classes:

__precedes__ that is a list of classes.  So, the fix for the above problem would be to define E as follows:

class E:
    from whatever import C
    __precedes__ = [C]

Then, when topologically-sorting (so-called linearizing) the ancestor classes, Python can try to ensure that E precedes C when defining B.


So it sounds like you are talking about the way that the siblings in the inheritance tree (the bases of each class) get "flattened" into the mro in a depth-first manner, and the relative order of siblings is not preserved.

It is preserved, but there are insufficient constraints, which causes problems with future class definitions.
 
What would you think about not topologically sorting the inheritance tree as such, but sorting a graph that has additional edges according to the base lists of each class involved? In this case those edges would be E->C, S->E, B->R. Is this what your talking about, or do I misinterpret the problem?

That's already part of the topological sorting algorithm.  You have to do that.  I'm suggesting additional constraints.
 

​​-- Koos


--
+ Koos Zevenhoven + http://twitter.com/k7hoven +