The current MRO algorithm prevents you from making hierarchies like the following:
class Abstract: ... class B(Abstract): ... class C(Abstract, B): ...
TypeError: Cannot create a consistent method resolution
order (MRO) for bases Abstract, B
An example of where this might occur is that the author intends that
C is a subtype of
C's implementation is totally different and it will not call
super().__init__(), and instead roll it’s own implementation. The author wants to reintroduce the abstract class to re-enable the
abstractmethod checking and get any default method implementations from
B may have overridden.
The error occurs because the linearization algorithm assumes that a class should only appear in the MRO once. That is a reasonable assumption, since you don’t want to call
__init__ on a class more than once. However,
Abstract is abstract and has no
__init__, so it is safe to appear in the MRO more than once (AFAICT). An appropriate MRO could be
[C, A, B, A]. Monotonicity is preserved, no constructor is called more than once, and the author’s intent is realized.
Concretely, I’m proposing that the linearization algorithm allow a class to appear in an MRO more than once, if it does not have an
__init__ overload. In the current C3 algorithm, when the condition of “no good next head” to the merge operation occurs, search the merge list left-to-right to see if any class does not have an
__init__. The first one that is found is added to the MRO, and the algorithm continues.
EDIT: Perhaps the real issue is that class MRO and
__init__ linearization should occur separately?