Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python class inheritance call order

There is a famous Python example

class A(object):
    def go(self):
        print("go A go!")

class B(A):
    def go(self):
        super(B, self).go()
        print("go B go!")

class C(A):
    def go(self):
        super(C, self).go()
        print("go C go!")

class D(B,C):
    def go(self):
        super(D, self).go()
        print("go D go!")


d = D()
d.go() 

#go A go!
#go C go!
#go B go!
#go D go!

I have several questions. The first one is B calls A and C calls A so I expect A to appear twice. The second question is about the order.

like image 913
com Avatar asked Mar 13 '18 04:03

com


1 Answers

Since Python 2.3, method resolution has used an algorithm called C3 Linearization (borrowed from Dylan). Wikipedia has a nice article on it.

As the name implies, the idea is to force the method resolution graph to be a straight line, even if the inheritance graph isn't. Which means A is not going to appear twice, by design.

Why? Well, for one thing, it completely avoids the "diamond problem" that plagues multiple inheritance in many other languages. (Or maybe it's more accurate to say that many other languages either ban MI or restrict it to pure "interfaces" because they didn't have a solution to the problem as it exists in C++.)

The original Python explanation—including the motivation behind it—is available in The Python 2.3 Method Resolution Order. This is a bit technical, but worth reading if you're interested.

You might also want to read the original Dylan paper, which goes into more detail about what's wrong with non-linear MRO graphs, and the challenges of coming up with a linearization that's monotonic (i.e., it goes in the order you expect, or at least the order you expect once you get over the fact that it's linear), and so on.

And if you want a deeper understanding of how type() works under the covers, or just want to see what's changed between 2.3 and 3.7 (e.g., the way __mro__ gets created and updated—although magic 3.x super is elsewhere), there's really no better place than the CPython source.

like image 188
abarnert Avatar answered Nov 07 '22 05:11

abarnert