當前位置:首頁 » 編程語言 » python新式類和經典類

python新式類和經典類

發布時間: 2022-04-16 14:06:41

python2.7.3和3.3.2的區別

轉自:http://my.oschina.net/chihz/blog/123437
這邊只說明面向對象方面的,其他方面見上面鏈接

面向對象
(1) 經典類和新式類
Python OO最神奇的地方就是有兩種類,經典類和新式類。
新式類跟經典類的差別主要是以下幾點:
1. 新式類對象可以直接通過__class__屬性獲取自身類型:type
2. 繼承搜索的順序發生了改變,經典類多繼承屬性搜索順序: 先深入繼承樹左側,再返回,開始找右側;新式類多繼承屬性搜索順序: 先水平搜索,然後再向上移動
3. 新式類增加了__slots__內置屬性, 可以把實例屬性的種類鎖定到__slots__規定的范圍之中。
4. 新式類增加了__getattribute__方法
Python 2.x中默認都是經典類,只有顯式繼承了object才是新式類
Python 3.x中默認都是新式類,不必顯式的繼承object
python 2.x:
>>> ClassicClass.__class__
Traceback (most recent call last):
File "<stdin>", line 1, in <mole>
AttributeError: class ClassicClass has no attribute '__class__'
>>> class NewClass(object):
... pass
...
>>> NewClass.__class__

python 3.x:
>>> class NewClass:pass
...
>>> NewClass.__class__
<class 'type'>
(2) 無綁定方法
在Python 2.x中除了類方法和靜態方法,其餘的方法都必須在第一個參數傳遞self跟實例綁定,但是在Python 3.x中廢除了這條規定,允許方法不綁定實例,這樣的方法跟普通的函數沒有區別:
Python 2.x:
>>> class MyClass:
... def function():
... print "function"
...
>>> MyClass.function()
Traceback (most recent call last):
File "<stdin>", line 1, in <mole>
TypeError: unbound method function() must be called with MyClass instance as first argument (got nothing instead)
>>> m = MyClass()
>>> m.function()
Traceback (most recent call last):
File "<stdin>", line 1, in <mole>
TypeError: function() takes no arguments (1 given)
Python 3.x:
>>> class MyClass:
... def function():
... print("function")
...
>>> MyClass.function()
function
>>> m = MyClass()
>>> m.function()
Traceback (most recent call last):
File "<stdin>", line 1, in <mole>
TypeError: function() takes no arguments (1 given)
(3) 重要的重載
1. next()和__next__():這應該是繼print之後第二大坑爹的不兼容吧,Python程序漫山遍野都是迭代器,但是2和3之間迭代器的實現介面方法名是不同的……嗯,啥都不說了。
2. 分片攔截:Python 3.x之前, 類可以定義__getslice__和__setslice__方法來專門攔截分片,並且這兩個方法優先於__getitem__和__setitem__, 但是Python 3.x時代這倆方法再也不存在了,全部的工作都交給了__getitem__和__setitem__,因此在使用這兩個方法之前要先判斷傳遞進參數的類型是不是slice對象。
3. __bool__方法:我們知道Python中默認將所有的空對象定義為布爾意義上的False,在自己定義的類中我們也可以加入自定義的布爾判斷標准,在2.x中這個方法名叫做__nonzero__, 這個名字顯然非常不直觀並且不科學!所有考試交白卷的孩子我們都要否定他們的才能么?顯然不能!因此Python 3.x中這個方法被重名命為__bool__
4. 3.x 取消了用於大小比較的__cmp__方法,取而代之的是:__lt__、__gt__、__le__、__ge__、__eq__、__ne__,嗯,我感覺這個想法真是不能苟同……有誰能說服我給我洗腦讓我愛上這一堆__lt__、__gt__、__le__、__ge__、__eq__、__ne__么。。。
(4) 類修飾器
在我的上一篇博客中秀了一把函數裝飾器在表單驗證中的使用,http://my.oschina.net/chihz/blog/122897
在3.x的時代,類也有裝飾器了,這個裝飾器威力巨大,能把裝飾的類搞的面目全非,總之想怎麼搞就怎麼搞,用法同函數裝飾器基本一致,只不過傳遞的參數是類型:
>>> def shutdown(cls):
... def shutdown_func(self):
... print("do something...")
... cls.shutdown = shutdown_func
... return cls
...
>>> @shutdown
... class Test:pass
...
>>> t = Test()
>>> t.shutdown()
do something...

異常

先來看一段代碼
python 2.x:
>>> class Person:
... def __init__(self, msg):
... self.msg = msg
...
>>> try:
... raise Person, "woca"
... except Person as p:
... print p.msg
...
woca
python 3.x:
>>> class Person:
... def __init__(self, msg):
... self.msg = msg
...
>>> try:
... raise Person("woca")
... except Person as p:
... print(p.msg)
Traceback (most recent call last):
File "<stdin>", line 2, in <mole>
TypeError: exceptions must derive from BaseException

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File "<stdin>", line 3, in <mole>
TypeError: catching classes that do not inherit from BaseException is not allowed
>>>
接下來說不同:
1. 在2.x時代,所有類型的對象都是可以被直接拋出的,在3.x時代,只有繼承自BaseException的對象才可以被拋出。
2. 2.x raise語句使用逗號將拋出對象類型和參數分開,3.x取消了這種奇葩的寫法,直接調用構造函數拋出對象即可。
在2.x時代,異常在代碼中除了表示程序錯誤,還經常做一些普通控制結構應該做的事情,在3.x中可以看出,設計者讓異常變的更加專一,只有在錯誤發生的情況才能去用異常捕獲語句來處理。

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

A.在Python里凡是繼承了object的類,都是新式類
B.Python3里只有新式類
C.Python2裡面繼承object的是新式類,沒有寫父類的是經典類
D.經典類目前在Python里基本沒有應用
E.保持class與type的統一對新式類的實例執行a.class與type(a)的結果是一致的,對於舊式類來說就不一樣了
F.對於多重繼承的屬性搜索順序不一樣新式類是採用廣度優先搜索,舊式類採用深度優先搜索

③ python經典類和新式類為啥效率差這么多

你的測試時間差別太誇張了,肯定受到其他程序的影響,用timeit測量了一下更好。

如果all_except函數是 current != node這種,大概舊式類的對象創建和遍歷加的操作是新式類對象的時間2倍。但是如果把all_except改成 while not current is node:那麼舊式類對象的操作時間就比新式類少(新式類有一個descriptor的查找過程),如果給新式類增加__slots__,時間能稍微降一點,但還是比舊式類多。

所以問題應該是 != 操作沒有 not is 操作高效,is操作使用了id,應該類似比較內存地址那種。而!=可能做了更多的事情。

下面是代碼。

import time
class dblink:
def __init__(self,index=0):
self.index = index
self.prev = self
self.next = self

def insert(self,index):
node = dblink(index)
node.prev = self.prev
node.next = self
self.prev.next = node
self.prev = node

class nt_dblink(object):
__slots__=('index','prev','next')
def __init__(self,index=0):
self.index = index
self.prev = self
self.next = self

def insert(self,index):
node = nt_dblink(index)
node.prev = self.prev
node.next = self
self.prev.next = node
self.prev = node

def all_except(node):
current = node.next
while not current is node:
yield current
current = current.next

def test1():
head = dblink()
for i in range(100000):
head.insert(i)

for node in all_except(head):
node.index+=1

def test2():
head = nt_dblink()
for i in range(100000):
head.insert(i)

for node in all_except(head):
node.index+=1

if __name__=='__main__':
import timeit
print(timeit.timeit("test1()", setup="from __main__ import test1",number=1))
print(timeit.timeit("test2()", setup="from __main__ import test2",number=1))

④ python經典類和新式類的區別

在Python 2及以前的版本中,由任意內置類型派生出的類(只要一個內置類型位於類樹的某個位置),都屬於「新式類」,都會獲得所有「新式類」的特性;反之,即不由任意內置類型派生出的類,則稱之為「經典類」。
「新式類」和「經典類」的區分在Python 3之後就已經不存在,在Python 3.x之後的版本,因為所有的類都派生自內置類型object(即使沒有顯示的繼承object類型),即所有的類都是「新式類」。

⑤ Python新式類和舊式類的區別

1)首先,寫法不一樣:

classA:#舊式類
pass

classB(object):#新式類
pass


2)在多繼承中,新式類採用廣度優先搜索,而舊式類是採用深度優先搜索。
3)新式類更符合OOP編程思想,統一了python中的類型機制。

⑥ Python 為什麼要繼承 object 類

繼承 object 類的是新式類,不繼承 object 類的是經典類
2.2以前的時候type和object還不統一. 在2.2統一以後到3之間, 要用class Foo(object)來申明新式類, 因為他的type是 < type 'type' > .不然的話, 生成的類的type就是 < type 'classobj' >
Python2 里的新式類, 其特點如下:

low-level constructors named __new__() – 低級別的構造函數.
Note: Python 的 class __init__ 並不是其他語言意義上的構造函數,
在 new 創建實例後對實例屬性初始化的函數.
descriptors, a generalized way to customize attribute access – 描述符.
或者說描述符協議支持.descriptor protocol __get__, __set__ ,__delete__ 等,
可以閱讀 descriptor 文檔
static methods and class methods - 靜態方法和類方法
properties (computed attributes) – 屬性訪問 setter getter.
decorators (introced in Python 2.4) – 裝飾器.
現在裝飾器語法糖遍布各Python框架.
slots – 用戶設置後可以限定實例的屬性.
在 Python2 中替代 __dict__, 可以節省近 2/3 內存, Python3 中可以
不因為優化內存使用率而使用 slots, 因為 __dict__ 結構內存做了優化,
Note: __dict__ 並不是 Python 意義上的內置的 dict, 其實是一個 proxy 類.
a new Method Resolution Order (MRO) – MRO 方法解析次序改變
(由左遞歸改為C3演算法)

⑦ python中怎麼組織這樣的類

我的思路是做類的繼承,不管是新式類還是經典類,在Python3上都是「廣度優先」,使用繼承的方式,當某個類的實例條件成立就轉向執行本身。

⑧ Python中的舊樣式類和新樣式類有什麼區別

  1. 在Python 2.1之前,舊式類是用戶可用的唯一樣式。

  2. (舊式)類的概念與類型的概念無關:如果x是舊式類的實例,則x.__class__指定的類x,但type(x)始終為<type
    'instance'>。這反映了這樣一個事實,即所有舊式實例(獨立於其類)均使用稱為實例的單個內置類型實現。

  3. 在Python 2.2中引入了新的類,以統一class和type的概念。新型類只是用戶定義的類型,不多也不少。如果x是新樣式類的實例,則type(x)通常與x 相同x.__class__(盡管不能保證–允許新樣式類實例覆蓋為返回的值x.__class__)。

  4. 引入新型類的主要動機是提供具有完整元模型的統一對象模型。

  5. 它還具有許多直接的好處,例如能夠對大多數內置類型進行子類化,或者引入了「描述符」,以啟用計算屬性。出於兼容性原因,默認情況下,類仍為舊樣式。通過將另一個新樣式類(即一種類型)指定為父類或「頂級類型」對象(如果不需要其他父類)來創建新樣式類。

  6. 新樣式類的行為與舊樣式類的行為不同,除了返回什麼類型外,還有許多重要的細節。其中一些更改是新對象模型的基礎,例如調用特殊方法的方式。其他是出於兼容性考慮而無法實現的「修復程序」,例如在多重繼承的情況下的方法解析順序。

  7. Python 3僅具有新型類。無論是否從中繼承子類object,類都是Python 3中的新型樣式。

⑨ python的多重繼承問題

樓上的回答的很正確,簡單來說:在對類D進行實例化的時候,你依次對類C和類A進行了初始化,結果就會以後初始化的B為准了

實際上在子類里並不需要去初始化父類,你在實例化子類的同時,繼承自父類的對象都會被創建

classA(object):
def__init__(self):
self.a=1

classB(A):
def__init__(self):
self.a=2
self.b=2
classC(B,A):
pass

>>> c = C()

>>> c.a

>>> 2

另外補充一下。父類為新式類的情況下,繼承順序是有影響的。繼承順序上,經典類是深度優先,新式類是廣度優先,兩種混用的話,分分鍾就暈乎了。可以去多做做實驗,好好了解。

熱點內容
解壓神經 發布:2024-04-19 21:47:03 瀏覽:894
c語言字元轉義字元 發布:2024-04-19 21:43:51 瀏覽:727
mysql存儲過程語法 發布:2024-04-19 21:00:04 瀏覽:245
修復損壞的壓縮文件 發布:2024-04-19 20:53:32 瀏覽:423
編程發型 發布:2024-04-19 20:53:28 瀏覽:500
去除空格sql 發布:2024-04-19 20:43:30 瀏覽:785
linuxcp覆蓋 發布:2024-04-19 20:43:30 瀏覽:189
mplayerlinux 發布:2024-04-19 20:33:57 瀏覽:800
華勤伺服器怎麼樣 發布:2024-04-19 20:33:15 瀏覽:410
安卓app應用程序擴展名是什麼 發布:2024-04-19 20:08:29 瀏覽:560