Python支持多繼承,與C++一樣都會出現一種問題:子類繼承的多個父類又繼承了同一個父類,這時就有可能會出現父類構造方法被調用多次的情況。關於這個問題,我找了一些資料,雖然沒有親自全部驗證,這里我總結一下自己對這個問題的看法。
Python和C++的關於這個問題的解決方案不太一樣,當然Python還要看它的版本。
C++用的方案是引入了虛繼承的語法避免同一個類被構造了多次。
Python用的方法是MRO(method resolution order,方法解析順序) 。在在Python2.3之前,MRO的實現是基於DFS的,而在Python2.3以后MRO的實現是基於C3算法。找到的資料解釋了一下更換算法的原因:

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()
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
如果我用的是super來解決多繼承的初始化問題的話,那么到底是怎么初始化的呢?
這是我一開始想到的一個問題:
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__(?)怎么寫?
我試了一下:
① ? = 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__()這個方法而且最靠左邊的那個父類的一個對象就可以了。
參考文章地址:
http://blog.csdn.net/imzoer/article/details/8737642
http://blog.csdn.net/zyflying/article/details/8636006