首頁  >  文章  >  後端開發  >  python2中的__new__與__init__,新式類別與經典類

python2中的__new__與__init__,新式類別與經典類

高洛峰
高洛峰原創
2016-10-18 09:35:181104瀏覽

在python2.x中,從object繼承得來的類別稱為新式類別(如class A(object))不會從object繼承得來的類別稱為經典類別(如class A())

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

  1. 新式類別物件可以直接透過__class__屬性取得自身類型:type

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

例子:

經典類: 搜索順序是( D,B,A,C)

>>> class A: attr = 1
...
>>> class B(A): pass
...
>>> class C(A): attr = 2
...
>>> class D(B,C): pass
...
>>> x = D()
>>> x.attr
1

   

新式類別繼承搜尋程式是寬度優先

新式類別:搜尋順序是(D,B,C,A)

>>> class A(object): attr = 1
...
>>> class B(A): pass
...
>>> class C(A): attr = 2
...
>>> class D(B,C): pass
...
>>> x = D()
>>> x.attr
2

類增加

33.了__slots__內建屬性, 可以把實例屬性的種類鎖定到__slots__規定的範圍之中。

  4.新式類別增加了__getattribute__方法

  5.新式類別內建有__new__方法而經典類別沒有__new__方法而只有__init__方法

注意:Pytyt 2.x中預設都是經典類,只有顯式繼承了object才是新式類別

     而Python 3.x中預設都是新式類別(也即object類別預設是所有類別的祖先),不必顯式的繼承object(可以依照經典類別的定義方式寫一個經典類別並分別在python2.x和3.x版本中使用dir函數檢定下。在2.x下沒有__new__方法而3.x下有。 __new__方法,會先呼叫__new__方法,__new__方法接受目前正在實例化的類別作為第一個參數(這個參數的類型是type,這個類型在c和python的交互編程中具有重要的角色,有興趣的可以搜下相關的資料),其傳回值是本次建立產生的實例,也就是我們熟知的__init__方法中的第一個參數self。得到? ,如果父類別沒有則繼續上溯)可以透過呼叫object的__new__方法類別得到這個實例(這實際上也和python中的預設機制基本一致),例如:

class display(object):
    def __init__(self, *args, **kwargs):
        print("init")
    def __new__(cls, *args, **kwargs):
        print("new")
        print(type(cls))
        return object.__new__(cls, *args, **kwargs)   
a=display()

   

運行上述程式碼會得到以下輸出:

new

init

因此我們可以得到以下結論:

在實例創建過程中__new__方法先於__init__方法被調用,它的第一個參數類型為type。得到這個實例,只要那個類別或其父類或祖先有__new__方法。這麼一個關係,__init__提供生產的原料self(但不保證這個原料來源正宗,像上面那樣它用的是另一個不相關的類的__new__方法類得到這個實例),而__init__就用__new__給的原料來完善這個物件(儘管它不知道這些原料是不是正宗的)

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn