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).

Original source

Related problems