最近在學習python的多重繼承。
先來了解下多重繼承的概念,所謂多重繼承,是指python的類可以有兩個以上父類,也即有類A,類B,類C,C同時繼承類A與類B,此時C中可以使用A與B中的屬性與方法。那么問題來了,如果A與B中具有相同名字的方法,這個時候python怎么調用的會是哪個方法呢?
舉個例子:
class A(object):
def __init__(self):
pass
def foo(self):
print 'A foo'
class B(object):
def __init__(self):
pass
def foo(self):
print 'B foo'
class C(A,B):
def __init__(self):
pass
testc = C()
testc.foo()
實際上打印出來的信息是 A foo,這就說明了調用的是A中的方法。其實在python2.2之后,多繼承中基類的尋找順序是一種廣度優先算法,稱之為C3的算法(后續博客我會簡單介紹下C3算法)。而python2.2之前,使用的是深度優先算法來尋找基類方法。在類C的繼承關系中,按照廣度優先算法,則會先找到靠近C的基類A,在A中找到foo方法之后,就直接返回了,因此即使后面的基類B中也有foo方法,但是這里不會引用它。
更加清晰的多繼承例子:
class A(object): def foo(self): print 'A foo' class B(object): def foo(self): print 'B foo' def bar(self): print 'B bar' class C1(A,B): pass class C2(A,B): def bar(self): print 'C2-bar' class D(C1,C2): pass if __name__ =='__main__':
print D.__mro__ #只有新式類有__mro__屬性,告訴查找順序是怎樣的 d=D() d.foo() d.bar()
執行的結果為:
(<class '__main__.D'>, <class '__main__.C1'>, <class '__main__.C2'>, <class '__main__.A'>, <class '__main__.B'>, <type 'object'>)
A foo (實際上搜索順序為D=>C1=>A)
C2 bar(實際上搜索順序為D=>C1=>C2)
可以看到,foo找到的是A類中的方法,bar找到的是C2中的方法。
其實新式類的搜索方法是采用了“廣度優先”的方式去查找屬性。
只有新式類有__mro__屬性,該屬性標記了python繼承層次中父類查找的順序,python多重繼承機制中就是按照__mro__的順序進行查找,一旦找到對應屬性,則查找馬上返回。
經過上面的__mro__輸出可以發現,D類的繼承查找路徑為:D=>C1=>C2=>A=>B=>object,通過該查找路徑,foo方法將會調用A的foo方法,、bar方法將調用C2的方法,通過實際實驗調用,查看輸出內容確實與__mro__順序一樣。