Basically, the idea behind C3 is that if you write down all of the ordering rules imposed by inheritance relationships in a complex class hierarchy, the algorithm will determine a monotonic ordering of the classes that satisfies all of them. If such an ordering can not be determined, the algorithm will fail.
Unfortunately, sometimes even when there is a consistent monotonic ordering, the current MRO implementation might be failed to find it. For example, the following code will raise an error:
class A: pass class B: pass class A0(A): pass class A1(A): pass class A0_B(A0, B): pass class B_A1(B, A1): pass class A0_B_A1(A0_B, B_A1): pass
TypeError: Cannot create a consistent method resolution order (MRO) for bases A, B
A workaround it to add more hints to the MRO. For example, we can change
class A0_B(A0, B) to
class A0_B(A0, B, A):
class A: pass class B: pass class A0(A): pass class A1(A): pass # Changed from `class A0_B(A0, B):` class A0_B(A0, B, A): pass class B_A1(B, A1): pass class A0_B_A1(A0_B, B_A1): pass
However, the workaround is not always possible, because the user of
B_A1 might not be able to change
I think the best solution is to perform a proper topological sorting when determining the MRO of a class, instead of merging the MROs of the base classes.