Python MRO is a linear ordering of the base classes that is used to decide the order in which inherited methods are overridden. As mentioned in @guido’s blog:
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 A0_B
and B_A1
might not be able to change A0_B
’s implementation.
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.