2

I was going through Effective Python book, And I found the folllowing code

class MyBaseClass(object):
    def __init__(self, value):
        self.value = value
        print "I changed it   to MyBaseClass",self.value

class TimesFiveCorrect(MyBaseClass):
    def __init__(self, value):
        super(TimesFiveCorrect, self).__init__(value)
        self.value *= 5
        print "I changed it   to TimesFiveCorrect ",self.value

class PlusTwoCorrect(MyBaseClass):
    def __init__(self, value):
        super(PlusTwoCorrect, self).__init__(value)
        self.value += 2
        print "I changed it   to PlusTwoCorrect ",self.value

class Factor(TimesFiveCorrect, PlusTwoCorrect):
    def  __init__(self, value):
        super(Factor, self).__init__(value)
        print "I changed it   to Factor ",self.value

foo = Factor(5)
from pprint import  pprint
pprint(Factor.mro())

What I expected the value of foo would be 27 (5 * 5 + 2). But it turns out to be 35. And the output is following

I changed it   to MyBaseClass 5
I changed it   to PlusTwoCorrect  7
I changed it   to TimesFiveCorrect  35
I changed it   to Factor  35
[<class '__main__.Factor'>,
 <class '__main__.TimesFiveCorrect'>,
 <class '__main__.PlusTwoCorrect'>,
 <class '__main__.MyBaseClass'>,
 <type 'object'>]

I could understand the MRO but I didn't get the execution order... Shouldn't TimesFiveCorrect be called first?

linusg
  • 6,289
  • 4
  • 28
  • 78
Ishan Bhatt
  • 9,287
  • 6
  • 23
  • 44
  • 1
    Possible duplicate of [How does Python's super() work with multiple inheritance?](http://stackoverflow.com/questions/3277367/how-does-pythons-super-work-with-multiple-inheritance) – Hooting May 09 '16 at 14:28

1 Answers1

2

But the MRO is the execution order, and your printout explains what is going on.

TimesFiveCorrect is called first. However, the first thing it does is to call the super method, which resolves to PlusTwoCorrect; that in turn calls its super method, which resolves to MyBaseClass. It is only when those methods all return that the value is mutated and the print statements happen.

If you wanted the result of 27, you could move the super() calls to the end of each method. The mutation and print would then happen first, before calling the super method.

Daniel Roseman
  • 588,541
  • 66
  • 880
  • 895
  • Ok, I get that but why does super in TimesFiveCorrect gets resolved to PlusTwoCorrect? Shouldn't it get resolved to MyBaseClass?? Or the call of super is in order of classes in MRO list? I thought TimesFiveCorrect and PlusTwoCorrect aren't related. But seems like they are.. – Ishan Bhatt May 09 '16 at 14:33
  • Yes that is *exactly* what MRO means. And you would probably benefit from reading Raymond Hettinger's classic post [Python's super() considered super](https://rhettinger.wordpress.com/2011/05/26/super-considered-super/). – Daniel Roseman May 09 '16 at 14:36