1.新式類與經典類html
在Python 2及之前的版本中,由任意內置類型派生出的類(只要一個內置類型位於類樹的某個位置),都屬於「新式類」,都會得到全部「新式類」的特性;反之,即不禁任意內置類型派生出的類,則稱之爲「經典類」。python
「新式類」和「經典類」的區分在Python 3以後就已經不存在,在Python 3.x以後的版本,由於全部的類都派生自內置類型object(即便沒有顯示的繼承object類型),即全部的類都是「新式類」。算法
官方文檔 https://www.python.org/doc/newstyle/函數
2.繼承順序的區別spa
主要是在多重繼承時纔會遇到這個問題。code
經典類的鑽石繼承是深度優先,即從下往上搜索;新式類的繼承順序是採用C3算法(非廣度優先)。htm
對經典類進行代碼驗證(全部經典類的代碼必須在Python2下運行,下同),ClassicClassB 繼承自 ClassicClassA,SubClassicClass繼承自ClassicClassB,ClassicClassC:blog
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
大概就想到這幾點,其餘的有想到再補充。