How does Python's super() work with multiple inheritance?
multiple-inheritance, python
Solution
This is detailed with a reasonable amount of detail by Guido himself in his blog post Method Resolution Order (including two earlier attempts).
In your example, `Third()` will call `First.__init__`. Python looks for each attribute in the class's parents as they are listed left to right. In this case, we are looking for `__init__`. So, if you define
class Third(First, Second):
...
Python will start by looking at `First`, and, if `First` doesn't have the attribute, then it will look at `Second`.
This situation becomes more complex when inheritance starts crossing paths (for example if `First` inherited from `Second`). Read the link above for more details, but, in a nutshell, Python will try to maintain the order in which each class appears on the inheritance list, starting with the child class itself.
So, for instance, if you had:
class First(object):
def __init__(self):
print "first"
class Second(First):
def __init__(self):
print "second"
class Third(First):
def __init__(self):
print "third"
class Fourth(Second, Third):
def __init__(self):
super(Fourth, self).__init__()
print "that's it"
the MRO would be `[Fourth, Second, Third, First].`
By the way: if Python cannot find a coherent method resolution order, it'll raise an exception, instead of falling back to behavior which might surprise the user.
Example of an ambiguous MRO:
class First(object):
def __init__(self):
print "first"
class Second(First):
def __init__(self):
print "second"
class Third(First, Second):
def __init__(self):
print "third"
Should `Third`'s MRO be `[First, Second]` or `[Second, First]`? There's no obvious expectation, and Python will raise an error:
TypeError: Error when calling the metaclass bases
Cannot create a consistent method resolution order (MRO) for bases Second, First
Why do the examples above lack `super()` calls? The point of the examples is to show how the MRO is constructed. They are not intended to print `"first\nsecond\third"` or whatever. You can – and should, of course, play around with the example, add `super()` calls, see what happens, and gain a deeper understanding of Python's inheritance model. But my goal here is to keep it simple and show how the MRO is built. And it is built as I explained:
>>> Fourth.__mro__
(<class '__main__.Fourth'>,
<class '__main__.Second'>, <class '__main__.Third'>,
<class '__main__.First'>,
<type 'object'>)
Problem
How does `super()` work with multiple inheritance? For example, given: ``` class First(object): def __init__(self): print "first" class Second(object): def __init__(self): print "second" class Third(First, Second): def __init__(self): super(Third, self).__init__() print "that's it" ``` Which parent method of `Third` does `super().__init__` refer to? Can I choose which runs? I know it has something to do with method resolution order (MRO).