这个系列的讲述,部分内容或者例子来自 <>


python 的类有经典类和新式类之分,在多重继承的时候,继承到的方法的搜索的顺序根据类的类型不同也是不同的。


先来讲经典类:


经典类的特点就是不继承自任何类:


#coding:utf-8

class p_1:
    def foo(self):
        print 'called p1-foo()'

class p_2:
    def foo(self):
        print 'called p2-foo()'

    def bar(self):
        print 'called p2-bar'

class c_1(p_1,p_2):
    pass

class c_2(p_1,p_2):
    def bar(self):
        print 'called c2-bar()'

class c_3(c_1,c_2):
    pass



c3 = c_3()
c3.foo()
c3.bar()

 

python 类 五 : 多重继承的MRO顺序_第1张图片


这个继承关系如上图所示


经典类的多重继承,子类对于继承到的父类的方法的搜索顺序是: 深度优先,从左至右。


那么,对于 c3这个实例,来自于类 c_3。


c_3没有自己实现 foo 和 bar 方法 。


那么,按照深度优先,从左至右的原则。


对于foo方法:

先找自己,自己没有实现foo,再向上找c_2 ,c_2也没有实现foo,继续向上找c_1,c_1也没有实现foo,继续向上找p_1,p_1实现了foo方法。

则c_3.foo()的输出是:called p1-foo()


对于bar方法:

先找自己,自己没有bar,再向上找c_1,c_1没有实现bar,继续向上找p_1,p_1实现了bar方法。

则c_3.bar()的输出是: called p2-bar 


而如果是新式类:


则MRO的搜索顺序是 广度优先,从左至右


则同样的代码(只是用新式类来声明):


#coding:utf-8

class p_1(object):
    def foo(self):
        print 'called p1-foo()'

class p_2(object):
    def foo(self):
        print 'called p2-foo()'
    def bar(self):
        print 'called p2-bar'

class c_1(p_1,p_2):
    pass

class c_2(p_1,p_2):
    def bar(self):
        print 'called c2-bar()'

class c_3(c_1,c_2):
    pass



c3 = c_3()
c3.foo()
c3.bar()


对于c3.foo()


先找c3自己,c_3自己没有实现foo,继续向上找c_1,c_1也没有实现foo,则找c_1的兄弟c_2,c_2也没有实现foo,则继续向上找p_1,p_1实现了foo

因此,c3.foo的输出是 called p1-foo()


对于c3.bar()


先找c3自己,c_3自己没有实现bar,则继续向上找c_1,c_1自己也没有实现bar,则继续找c_1的兄弟c_2,c_2实现了bar方法。


则c3.bar的输出是 called c2-bar()


总结:

对于新式类,是广度优先,从左至右的顺序搜索。

对于经典类,是深度优先,从左至右的顺序搜索。