Show the method resolution order of a Python class with multiple inheritance, and follow it.
Every Python class has a method resolution order, which is the list of classes that the interpreter searches when it looks for an attribute. You can look at it directly with the __mro__ attribute.
class A:
def name(self):
return 'A'
class B(A):
def name(self):
return 'B'
class C(A):
def name(self):
return 'C'
class D(B, C):
pass
print(D.__mro__)
print(D().name()) # B
The method resolution order is D, B, C, A, object. The search starts at D, finds nothing there, moves on to B, and finds name there. So the version from B wins, even though C also defines it.
The rule that produces this order is that the search is depth-first and from left to right, with the extra condition that no class may appear twice. A depth-first search from D would give you D, B, A, C, but A is already in the list at that point. So when the search reaches C and tries to add A, A is taken out of that position and placed after C instead. The result is the linearisation shown above.
Two more things are worth noticing. The order of the base classes in the definition matters, because writing class D(C, B) would give the opposite result and C would win. And A appears after both B and C rather than being visited twice, which is what stops the shared ancestor from being searched in two separate branches.