6

How does Python's super() work with multiple inheritance?

I was looking at the above question/answers and made myself really confused

 53 class First(object):
 54     def __init__(self):
 55         print "first"
 56
 57 class Second(First):
 58     def __init__(self):
 59         super(Second, self).__init__()
 60         print "second"
 61
 62 class Third(First):
 63     def __init__(self):
 64         print "third"
 65
 66 class Fourth(Second, Third):
 67     def __init__(self):
 68         super(Fourth, self).__init__()
 69         print "thats it"

Fourth()
third
second
thats it

 53 class First(object):
 54     def __init__(self):
 55         print "first"
 56
 57 class Second(First):
 58     def __init__(self):
 59         #super(Second, self).__init__()         <---- commented out
 60         print "second"
 61
 62 class Third(First):
 63     def __init__(self):
 64         print "third"
 65
 66 class Fourth(Second, Third):
 67     def __init__(self):
 68         super(Fourth, self).__init__()
 69         print "thats it"

Fourth()
second
thats it

Could someone explain to me what's happening behind the scene in regards to why the top prints "third" and the bottom one doesn't?

I feel like there is some sort of order/sequence that's happening behind the scene that I am not seeing.

-- Fourth.mro

commented out super in Second
(, , , , )

super in Second
(, , , , )

9
  • maybe a duplicate of How does Python's super() work with multiple inheritance?? Commented Oct 14, 2013 at 17:16
  • 4
    @SaulloCastro but thats the question that I linked to... Commented Oct 14, 2013 at 17:19
  • @ealeon Look at Fourth.__mro__, that's the order super() follows. Commented Oct 14, 2013 at 17:24
  • 2
    @hcwhsa yes but mro is the same regardless whether Second has super() or not? how does something that's in Second affects whether Third gets invoked or not? Commented Oct 14, 2013 at 17:31
  • 1
    @ealeon super() call in Second invokes next item in MRO, not super of Second. That's how Mixins work. Read: rhettinger.wordpress.com/2011/05/26/super-considered-super Commented Oct 14, 2013 at 17:34

2 Answers 2

5

super doesn't actually call the super class. It calls the next method according to the Method Resolution Order (MRO). It looks like the MRO for your example classes is as follows:

Fourth
Second
Third
First

That is, using super from Fourth gets you a method on Second. Using super from Second gets you a method on Third. etc.

In the first example:

  1. Fourth.__init__ is called.
  2. Fourth.__init__ calls Second.__init__ via super.
  3. Second.__init__ calls Third.__init__ via super.
  4. Third.__init__ prints "third"
  5. Second.__init__ prints "second"
  6. Fourth.__init__ prints "that's it".

In the second example:

  1. Fourth.__init__ is called.
  2. Fourth.__init__ calls Second.__init__ via super.
  3. Second.__init__ prints "second"
  4. Fourth.__init__ prints "that's it".

So, yes, changing a super call in Second changes whether something on Third is called, even though Third is not a super class of Second. This is indeed confusing. I recommend reading "Python's Super is nifty, but you can't use it". That's the explanation I read that got the above to make sense to me.

Sign up to request clarification or add additional context in comments.

1 Comment

Another related article: Python’s super() considered super!
4

The MRO is not a nested hierarchy. It is a flat list that obeys a set of constraints, namely that each class must precede its base classes, and those base classes must exist in the same order relative to each other as they are mentioned in the subclass declaration.

By printing Fourth.__mro__, we can see the MRO in your examples is:

(<class '__main__.Fourth'>, 
<class '__main__.Second'>, 
<class '__main__.Third'>, 
<class '__main__.First'>, 
<type 'object'>)

Each call to super that is set off will call the next method in the MRO. You can think of the number of super calls as the zero indexed "depth" into the MRO to which you will descend.

Since there are two calls to super in the first snippet, Second.__init__ and Third.__init__ are called (in addition, of course, to the immediate class' init method). Similarly, in the second snippet you have a single call to super, which means only Second.__init__ will be called.

2 Comments

How did you get that tuple output?
@NealEhardt print Fourth.__mro__

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.