多重繼承時,需要明確的是,當你多重繼承父類時,調用父類對應方法的關系。總結起來是,經典類中,使用深度優先,從左至右進行搜索;新式類中,它首先查找同胞兄弟,采用一種廣度優先的方式。
- class P1: #(object): # parent class 1
- def foo(self):
- print 'called P1-foo()'
- class P2: #(object): # parent class 2
- def foo(self):
- print 'called P2-foo()'
- def bar(self):
- print 'called P2-bar()'
- class C1(P1, P2): # child 1 derived from P1, P2
- pass
- class C2(P1, P2): # child 2 derived from P1, P2
- def bar(self):
- print 'called C2-bar()'
- class GC(C1, C2): # define grandchild class
- pass # derived from C1 and C2
下面這張圖描述了父類,子類及子孫類的關系圖,還有它們各自定義的方法:
首先來使用經典類:
- >>> gc = GC()
- >>> gc.foo() # GC ==> C1 ==> P1
- called P1-foo()
- >>> gc.bar() # GC ==> C1 ==> P1 ==> P2
- called P2-bar()
當調用foo()時,它首先在當前類(GC)中查找。如果沒找到,就向上查找最親的父類,C1。查找未遂,就繼續沿樹上訪到父類P1,foo()被找到。同样,對bar()來說,它通過搜索GC,C1,P1 然後在P2 中找到。因为使用這種解釋順序的緣故,C2.bar()根本就不會被搜索了。
取消類P1 和類P2 聲明中的對(object)的注釋,即使用新式類:
- >>> gc = GC()
- >>> gc.foo() # GC ==> C1 ==> C2 ==> P1
- called P1-foo()
- >>> gc.bar() # GC ==> C1 ==> C2
- called C2-bar()
與沿着繼承樹一步一步上溯不同,它首先查找同胞兄弟,采用一種廣度優先的方式。當查找foo(),它檢查GC,然後是C1 和C2,然後在P1 中找到。如果P1 中沒有,查找將會到達P2。當查找bar(),它搜索GC 和C1,緊接着在C2 中找到了。這样,就不會再繼續搜索到祖父P1 和P2。
新式類也有一個__mro__屬性,告訴你查找順序是怎样的:
>>> GC.__mro__
(<class '__main__.GC'>, <class '__main__.C1'>, <class
'__main__.C2'>, <class '__main__.P1'>, <class
'__main__.P2'>, <type 'object'>)