Python新式類和經典類的區別

2021-08-07 13:49:09 字數 4302 閱讀 8837

從python2.2開始,python 引入了 new style class(新式類)

新式類跟經典類的差別主要是以下幾點:

新式類物件可以直接通過__class__屬性獲取自身型別:type

[python]view plain

copy

# -*- coding:utf-8 -*-  

class

e:    

#經典類

pass

class

e1(object):    

#新式類

pass

e = e()  

print

"經典類"

print

e  print

type(e)  

print

e.__class__  

print

"新式類"

e1 = e1()  

print

e1  

print

e1.__class__  

print

type(e1)  

[python]view plain

copy

經典類  

<__main__.e instance at 0x0000000002250b08

>  

'instance'

>  

__main__.e  

新式類  

<__main__.e1 object at 0x0000000002248710

>  

'__main__.e1'

>  

'__main__.e1'

>  

我使用的是python 2.7。

e1是定義的新式類。那麼輸輸出e1的時候,不論是type(e1),還是e1.__class__都是輸出的。

2. 繼承搜尋的順序發生了改變,經典類多繼承屬性搜尋順序: 先深入繼承樹左側,再返回,開始找右側;新式類多繼承屬性搜尋順序: 先水平搜尋,然後再向上移動

[python]view plain

copy

# -*- coding:utf-8 -*-  

class

a(object):    

"""新式類

作為所有類的基類

"""def

foo(

self

):    

print

"class a"

class

a1():    

"""經典類

作為所有類的基類

"""def

foo(

self

):    

print

"class a1"

class

c(a):    

pass

class

c1(a1):    

pass

class

d(a):    

deffoo(

self

):    

print

"class d"

class

d1(a1):    

deffoo(

self

):    

print

"class d1"

class

e(c, d):    

pass

class

e1(c1, d1):    

pass

e = e()  

e.foo()  

e1 = e1()  

e1.foo()   輸出

[python]view plain

copy

class

d  class

a1  

因為a新式類,對於繼承a類都是新式類,首先要查詢類e中是否有foo(),如果沒有則按順序查詢c->d->a。它是一種廣度優先查詢方式。

因為a1經典類,對於繼承a1類都是經典類,首先要查詢類e1中是否有foo(),如果沒有則按順序查詢c1->a1->d1。它是一種深度優先查詢方式。

3. 新式類增加了__slots__內建屬性, 可以把例項屬性的種類鎖定到__slots__規定的範圍之中。

比如只允許對a例項新增name和age屬性:

[python]view plain

copy

# -*- coding:utf-8 -*-  

class

a(object):    

__slots__ = ('name'

, 'age'

)   

class

a1():    

__slots__ = ('name'

, 'age'

)   

a1 = a1()  

a = a()  

a1.name1 = "a1"

a.name1 = "a"

a是新式類新增了__slots__ 屬性,所以只允許新增 name age

a1經典類__slots__ 屬性沒用,

[python]view plain

copy

traceback (most recent call last):  

file "t.py"

, line 

13, 

ina.name1 = "a"

attributeerror: 'a'

object has no attribute 

'name1'

所以a.name是會出錯的

通常每乙個例項都會有乙個__dict__屬性,用來記錄例項中所有的屬性和方法,也是通過這個字典,可以讓例項繫結任意的屬性

而__slots__屬性作用就是,當類c有比較少的變數,而且擁有__slots__屬性時,

類c的例項 就沒有__dict__屬性,而是把變數的值存在乙個固定的地方。如果試圖訪問乙個__slots__中沒有

的屬性,例項就會報錯。這樣操作有什麼好處呢?__slots__屬性雖然令例項失去了繫結任意屬性的便利,

但是因為每乙個例項沒有__dict__屬性,卻能有效節省每乙個例項的記憶體消耗,有利於生成小而精

幹的例項。

4. 新式類增加了__getattribute__方法

[python]view plain

copy

class

a(object):    

def__getattribute__(

self

, *args, **kwargs):    

print

"a.__getattribute__"

class

a1():    

def__getattribute__(

self

, *args, **kwargs):    

print

"a1.__getattribute__"

a1 = a1()  

a = a()  

a.test  

print

"*****===="

a1.test  

[python]view plain

copy

a.__getattribute__  

*****====  

traceback (most recent call last):  

file "t.py"

, line 

18, 

ina1.test  

attributeerror: a1 instance has no attribute 'test'

可以看出a是新式類,每次通過例項訪問屬性,都會經過__getattribute__函式,

a1不會呼叫__getattribute__所以出錯了

python 2.x中預設都是經典類,只有顯式繼承了object才是新式類

python 3.x中預設都是新式類,不必顯式的繼承object

python新式類和經典類的區別

父類或者以上有繼承的object就是新式類 沒有的則是經典類 1,新式類和經典類的區別 廣度優先和深度優先,這主要是在多類繼承的時候會使用到,如下多類繼承的d類對比 新式類 和 經典類 的區分在python 3之後就已經不存在,在python 3.x之後的版本,因為所有的類都派生自內建型別objec...

Python新式類和經典類的區別

從python2.2開始,python 引入了 new style class 新式類 新式類跟經典類的差別主要是以下幾點 新式類物件可以直接通過 class 屬性獲取自身型別 type python view plain copy coding utf 8 class e 經典類 pass cla...

Python中新式類和經典類的區別

本文參考python核心程式設計一書class mynewobjecttype bases define mynewobjecttype class class suite 類體新式類和經典類的最大不同之處在於,所有的新式類必須至少乙個父類,引數bases可以是乙個或者多個用於繼承的父類。objec...