Python支持多繼承,與C++同樣都會出現一種問題:子類繼承的多個父類又繼承了同一個父類,這時就有可能會出現父類構造方法被調用屢次的狀況。關於這個問題,我找了一些資料,雖然沒有親自所有驗證,這裏我總結一下本身對這個問題的見解。算法
Python和C++的關於這個問題的解決方案不太同樣,固然Python還要看它的版本。函數
C++用的方案是引入了虛繼承的語法避免同一個類被構造了屢次。spa
Python用的方法是MRO(method resolution order,方法解析順序) 。在在Python2.3以前,MRO的實現是基於DFS的,而在Python2.3之後MRO的實現是基於C3算法。找到的資料解釋了一下更換算法的緣由:.net
1 # -*- coding:utf-8 -*- 2 3 class D(object): 4 def foo(self): 5 print "class D" 6 7 class B(D): 8 pass 9 10 class C(D): 11 def foo(self): 12 print "class C" 13 14 class A(B, C): 15 pass 16 17 f = A() 18 f.foo()
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------code
若是我用的是super來解決多繼承的初始化問題的話,那麼究竟是怎麼初始化的呢?對象
這是我一開始想到的一個問題:blog
1 class A(object): 2 def __init__(self,a): 3 print a 4 5 class B(object): 6 def __init__(self,a,b): 7 print a+b 8 9 class C(A,B): 10 def __init__(self): 11 super(C,self).__init__(?) 12 13 obj = C()
第十一行的那個'?'的位置究竟是填是什麼進去纔對呢?繼承
我一開始認爲由於是多繼承多以須要初始化父類的時候A,B都須要初始化,那麼問題來了,super(C,self).__init__(?)怎麼寫?utf-8
我試了一下:get
① ? = 1 --> 輸出1
② ? = 1,2 --> TypeError: __init__() takes exactly 2 arguments (3 given)
定義C的時候改爲class(B,A)
③ ? = 1 --> TypeError: __init__() takes exactly 3 arguments (2 given)
④ ? =1,2 --> 輸出3
再來看另外一段代碼:
1 class A(object): 2 def func(self): 3 print 1 4 5 class B(object): 6 def __init__(self): 7 print 2 8 9 class C(A,B): 10 def __init__(self): 11 super(C,self).__init__() 12 13 obj = C() 14 #The output is 3
說明什麼問題?在調用super(classname,self).__init__()的時候應該調用在繼承的父類列表裏面有實現__init__()這個方法並且最靠左邊的那個父類的構造方法,並且這個__init__(?)的'?'必定要與父類列表的裏面第一個有構造方法的父類的構造方法簽名同樣才能夠。
因此若是須要對全部父類都進行一遍初始化,仍是使用類經過類名調用未綁定的初始化方法好(我說這一句話是由於我還不是很瞭解super)。
說一下super的使用:
super( classname,對象(通常狀況是self) ) 返回的是一個super對象,你能夠把它看成父類列表裏面有實現__init__()這個方法並且最靠左邊的那個父類的一個對象就能夠了。
參考文章地址: