從python2.2開始,python 引入了 new style class(新式類)
新式類跟經典類的差別主要是以下幾點:
新式類物件可以直接通過__class__屬性獲取自身型別:type
[python]view plain
copy
# -*- coding:utf-8 -*-
class
e:
#經典類
pass
class
e1(object):
#新式類
pass
e = e()
"經典類"
e print
type(e)
e.__class__
"新式類"
e1 = e1()
e1
e1.__class__
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
):
"class a"
class
a1():
"""經典類
作為所有類的基類
"""def
foo(
self
):
"class a1"
class
c(a):
pass
class
c1(a1):
pass
class
d(a):
deffoo(
self
):
"class d"
class
d1(a1):
deffoo(
self
):
"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):
"a.__getattribute__"
class
a1():
def__getattribute__(
self
, *args, **kwargs):
"a1.__getattribute__"
a1 = a1()
a = a()
a.test
"*****===="
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...