1.新式類與經典類
在Python 2及以前的版本中,由任意內置類型派生出的類(只要一個內置類型位於類樹的某個位置),都屬於“新式類”,都會獲得所有“新式類”的特性;反之,即不由任意內置類型派生出的類,則稱之為“經典類”。
“新式類”和“經典類”的區分在Python 3之后就已經不存在,在Python 3.x之后的版本,因為所有的類都派生自內置類型object(即使沒有顯示的繼承object類型),即所有的類都是“新式類”。
官方文檔 https://www.python.org/doc/newstyle/
2.繼承順序的區別
主要是在多重繼承時才會遇到這個問題。
經典類的鑽石繼承是深度優先,即從下往上搜索;新式類的繼承順序是采用C3算法(非廣度優先)。
對經典類進行代碼驗證(所有經典類的代碼必須在Python2下運行,下同),ClassicClassB 繼承自 ClassicClassA,SubClassicClass繼承自ClassicClassB,ClassicClassC:
class ClassicClassA(): var = 'Classic Class A' class ClassicClassB(ClassicClassA): pass class ClassicClassC(): var = 'Classic Class C' class SubClassicClass(ClassicClassB, ClassicClassC): pass if __name__ == '__main__': print(SubClassicClass.var)
在SubClassicClass對var屬性進行搜索的過程中,根據從下到上的原則,會優先搜索ClassicClassB,而ClassicClassB沒有var屬性,會繼續往上搜索ClassicClassB的超類ClassicClassA,在ClassicClassA中發現var屬性后停止搜索,var的值為ClassicClassA中var的值;而ClassicClassC的var屬性從始至終都未被搜索到。
從運行結果可以看出,輸出的是Classic Class A,可見類繼承的搜索是深度優先,由下至上進行搜索。
Classic Class A
新式類的繼承順序並非是廣度優先,而是C3算法,只是在部分情況下,C3算法的結果恰巧與廣度優先的結果相同。
對新式類的繼承搜索順序進行代碼驗證,新式類中,可以使用mro函數來查看類的搜索順序(這也算是一個區別),如SubNewStyleClass.mro()。
class NewStyleClassA(object): var = 'New Style Class A' class NewStyleClassB(NewStyleClassA): pass class NewStyleClassC(NewStyleClassA): var = 'New Style Class C' class SubNewStyleClass(NewStyleClassB, NewStyleClassC): pass if __name__ == '__main__': print(SubNewStyleClass.mro()) print(SubNewStyleClass.var)
從代碼運行結果看,恰巧與從左至右的廣度優先預期結果相同。
[<class '__main__.SubNewStyleClass'>, <class '__main__.NewStyleClassB'>, <class '__main__.NewStyleClassC'>, <class '__main__.NewStyleClassA'>, <type 'object'>] New Style Class C
但是不代表新式類的繼承順序就是廣度優先,可以稍微修改下代碼進行驗證:NewStyleClassC改為繼承自object
class NewStyleClassA(object): var = 'New Style Class A' class NewStyleClassB(NewStyleClassA): pass class NewStyleClassC(object): var = 'New Style Class C' class SubNewStyleClass(NewStyleClassB, NewStyleClassC): pass if __name__ == '__main__': print(SubNewStyleClass.mro()) print(SubNewStyleClass.var)
運行結果不再符合廣度優先:
[<class '__main__.SubNewStyleClass'>, <class '__main__.NewStyleClassB'>, <class '__main__.NewStyleClassA'>, <class '__main__.NewStyleClassC'>, <type 'object'>] New Style Class A
可見,新式類的繼承順序並非廣度優先,而是C3算法。至於C3算法,以后再另外詳細寫。
3.類實例類型的區別
在經典類中,所有的類都是classobj類型,而類的實例都是instance類型。類與實例只有通過__class__屬性進行關聯。這樣在判斷實例類型時,就會造成不便:所有的實例都是instance類型。
class A():pass class B():pass a = A() b = B() if __name__ == '__main__': print(type(a)) print(type(b)) print(type(a) == type(b))
type(a) == type(b)的結果永遠為True,那這樣的比較就毫無意義。
更為麻煩的是,經典類的實例是instance類型,而內置類的實例卻不是,無法統一。
通過代碼判斷下內置類型list的實例[1, 2, 3]是什么類型
print(type([1, 2, 3]))
運行結果,是list類型
<type 'list'>
內置類的實例類型和經典類的實例類型完全不同,容易造成困惑,不利於代碼的統一。
這個問題在Python 3之后就不復存在了,因為Python3中所有的類都是新式類,新式類中類與類型已經統一:類實例的類型是這個實例所創建自的類(通常是和類實例的__class__相同),而不再是Python 2.x版本中的“instance”實例類型。
更詳細的:http://www.cnblogs.com/blackmatrix/p/5594109.html
大概就想到這幾點,其他的有想到再補充。