這個系列的講述,部分內容或者例子來自 <<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()
這個繼承關係如上圖所示
經典類的多重繼承,子類對於繼承到的父類的方法的搜索順序是: 深度優先,從左至右。
那麼,對於 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()
總結:
對於新式類,是廣度優先,從左至右的順序搜索。
對於經典類,是深度優先,從左至右的順序搜索。