SoFunction
Updated on 2024-10-28

Multiple inheritance in python explained by example

python, like C++, supports multiple inheritance. While the concept is easy, the hard work is that if a subclass calls a property that it doesn't define itself, in what order does it go to the parent class to find it, especially when more than one of the many parent classes contain that same property.

The order in which attributes are looked up is different for classic and new-style classes. Now let's look at the two different representations of classic and new-style classes separately:

Classics:

Copy Code The code is as follows.

#! /usr/bin/python
# -*- coding:utf-8 -*-

class P1():
    def foo(self):
        print 'p1-foo'

class P2():
    def foo(self):
        print 'p2-foo'
    def bar(self):
        print 'p2-bar'

class C1(P1,P2):
    pass

class C2(P1,P2):
    def bar(self):
        print 'C2-bar'

class D(C1,C2):
    pass


if __name__ =='__main__':
    d=D()
    ()
    ()

Results of implementation:

Copy Code The code is as follows.

p1-foo
p2-bar

Example of the code, with a diagram drawn for ease of understanding:

From the output of the classic class above, the

When instance d calls foo(), the search order is D => C1 => P1, the

When instance d calls bar(), the search order is D => C1 => P1 => P2

Summarize: The classic class search is in accordance with the "left to right, depth first" way to find the attributes. d First find out if there is a foo method in itself, if not, then find out if there is such a method in the nearest parent class C1, if not, then continue to look up until you find the method in P1, and the search is over.

New Style Class:

Copy Code The code is as follows.

#! /usr/bin/python
# -*- coding:utf-8 -*-

class P1(object):
    def foo(self):
        print 'p1-foo'
       
class P2(object):
    def foo(self):
        print 'p2-foo'
    def bar(self):
        print 'p2-bar'
       
class C1(P1,P2):
    pass
   
class C2(P1,P2):
    def bar(self):
        print 'C2-bar'
       
class D(C1,C2):
    pass
   

if __name__ =='__main__':
print D.__mro__ #Only new-style classes have the __mro__ attribute, which tells what the lookup order will be
    d=D()
    ()
    ()

Results of implementation:

Copy Code The code is as follows.

(<class '__main__.D'>, <class '__main__.C1'>, <class '__main__.C2'>, <class '__main__.P1'>, <class '__main__.P2'>, <type 'object'>)

p1-foo
C2-bar

From the output of the new-style class above, the

When instance d calls foo(), the search order is D => C1 => C2 => P1

When instance d calls bar(), the search order is D => C1 => C2

To summarize: the new style of class searching uses a "breadth-first" approach to find attributes.