Multiple inheritance with ABC: which order?

I am making an abstract base class that inherits another ABC (collections.abc.Mapping).

How is it better to order inheritance:
1)

class MyClass(ABC, collections.abc.Mapping):
    ...

OR
2)

class MyClass(collections.abc.Mapping, ABC):
    ...

i.e. inherit ABC first or last?

Python will always create a linear order for all base classes of a class and its parents and parents parents, etc. called the method resolution order (MRO). Then when an attribute is looked up on an instance, it will be found on the first class in that order. The way this order is decided guarantees two things: if some class in the inheritance hierarchy lists bases A and B then A must occur before B in the method resolution order. And similarly, if a class A inherits from B then it will occur before B.

But this means that if Mapping inherits from ABC, this forces the MRO to have Mapping first, but if you then write MyClass(ABC, Mapping), ABC must come first. Since you can’t have both before the other, Python can’t generate a consistent MRO and will throw an error. So whenever you inherit from both a class and one of that class’s bases, you must list the common base after the intermediate class.

But weirdly enogh, collections.abc.Mapping does not actually inherit from ABC. Rather, it (and the other collections.abc classes are implemented as Protocols that also pretend like they’re ABCs. So with these you can actually choose which order you want. Since ABC doesn’t implement any attributes, it doesn’t really matter where in the MRO it is. From what I’ve seen, most people put it last since it isn’t really a base class in a functionality sense and more just an indicator of intent.

2 Likes