python 類 五 : 多重繼承的MRO順序


這個系列的講述,部分內容或者例子來自 <<python 核心編程 第二版>>


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()

 

wKiom1fyiQfiKszcAAAsq7mGBgE911.jpg-wh_50


這個繼承關係如上圖所示


經典類的多重繼承,子類對於繼承到的父類的方法的搜索順序是: 深度優先,從左至右。


那麼,對於 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()


總結:

對於新式類,是廣度優先,從左至右的順序搜索。

對於經典類,是深度優先,從左至右的順序搜索。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章