Python新式類與經典類的區別

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

 

 

大概就想到這幾點,其餘的有想到再補充。

相關文章
相關標籤/搜索