Inheritance Diamonds

Multiple Inheritance

Inheritance is pretty neat! As you know, by inheriting from another class, you automatically get access to its instance variables and methods! Cool.

But did you know that in Python, you can inherit from multiple classes? Check this out.

Sidenote: for those of you who don’t know, pass is a keyword in Python which basically tells Python to ignore this method for now, and you’ll come back to it later. It’s a useful way of filling in methods later on without having Python complain at you.

class A(object):
    pass

class B(A):
    pass

class C(A):
    pass

Here we have the standard inheritance example – you have one class, A, which inherits from object. Then you have a class B which inherits from class A. Similar to B, you have another class C, which also inherits from A. Nothing new so far. But Python actually allows us to do this:

class D(B, C):
    pass

Woah. Class D inherits from both B and C!

Method Resolution Order

Some languages, like Java, actually forbid multiple inheritance. Generally speaking, it’s a can of worms that Object Oriented Programs like to avoid. But Python’s philosophy is one of flexibility, and sometimes you want this.

One problem that it introduces is called the inheritance diamond. Let’s take an example.

class A(object):
    def hola(self):
        print 'A'

class B(A):
    def hola(self):
        print 'B'

class C(A):
    def hola(self):
        print 'C'

class D(B, C):
    pass

Can you see where the “diamond” comes from?

            A
           / \
           B  C
            \/
            D

The above demonstrates the inheritance tree of the four classes we’ve defined, and it makes a diamond shape, roughly. The classes A, B, and C are quite simple.

As we expect, A().hola() outputs A, B().hola() outputs B, and C().hola() outputs C. So here’s the question: what does D().hola() output!?

Remember, D automatically inherits all the methods of its super classes. B inherits A’s hola method, but it overwrites it with its own hola method. Easy enough. Same thing with C. But if D inherits from both B and C, which hola method does it receive?

This exact dilemma is why Java does not allow multiple inheritance.

In Python, however, we have something called method resolution order. What is this? When you say D().hola(), the class D must look for a method hola somewhere. The method resolution order, or MRO, determines what order in which it finds the methods. Does it find A’s hola first, or B’s hola? These questions are determined by the MRO.

>>> print D.__mro__
(<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <type 'object'>)

Interesting. Look at the order here. First, it has everything from its own class, D. That makes sense. Next, it gets everything from class B. So in other words, if it can’t find hola in its own class, it tries to find it in class B. If it still can’t find any method named hola, it goes into class C to find it.

So our hypothesis is that D().hola() should print B, right? Let’s test that.

>>> D().hola()
B

Voila! MRO resolves the inheritance diamond problem! Pretty nifty.