程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 更多編程語言 >> 更多關於編程 >> Python中__new__與__init__方法的區別詳解

Python中__new__與__init__方法的區別詳解

編輯:更多關於編程

       這篇文章主要介紹了Python中__new__與__init__方法的區別,是Python學習中的基礎知識,需要的朋友可以參考下

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

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

      1. 新式類對象可以直接通過__class__屬性獲取自身類型:type

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

      例子:

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

      ?

    1 2 3 4 5 6 7 8 9 10 11 >>> 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)

      ?

    1 2 3 4 5 6 7 8 9 10 11 >>> class A(object): attr = 1 ... >>> class B(A): pass ... >>> class C(A): attr = 2 ... >>> class D(B,C): pass ... >>> x = D() >>> x.attr 2

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

      4. 新式類增加了__getattribute__方法

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

      注意:Python 2.x中默認都是經典類,只有顯式繼承了object才是新式類

      而Python 3.x中默認都是新式類(也即object類默認是所有類的祖先),不必顯式的繼承object(可以按照經典類的定義方式寫一個經典類並分別在python2.x和3.x版本中使用dir函數檢驗下。

      例如:

      ?

    1 2 3 4 5 class A():         pass       print(dir(A))

      會發現在2.x下沒有__new__方法而3.x下有。

      接下來說下__new__方法和__init__的區別:

      在python中創建類的一個實例時,如果該類具有__new__方法,會先調用__new__方法,__new__方法接受當前正在實例化的類作為第一個參數(這個參數的類型是type,這個類型在c和python的交互編程中具有重要的角色,感興趣的可以搜下相關的資料),其返回值是本次創建產生的實例,也就是我們熟知的__init__方法中的第一個參數self。那麼就會有一個問題,這個實例怎麼得到?

      注意到有__new__方法的都是object類的後代,因此如果我們自己想要改寫__new__方法(注意不改寫時在創建實例的時候使用的是父類的__new__方法,如果父類沒有則繼續上溯)可以通過調用object的__new__方法類得到這個實例(這實際上也和python中的默認機制基本一致),如:

      ?

    1 2 3 4 5 6 7 8 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()

      運行上述代碼會得到如下輸出:

      ?

    1 2 3 4 5 new   <class 'type'>   init

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

      在實例創建過程中__new__方法先於__init__方法被調用,它的第一個參數類型為type。

      如果不需要其它特殊的處理,可以使用object的__new__方法來得到創建的實例(也即self)。

      於是我們可以發現,實際上可以使用其它類的__new__方法類得到這個實例,只要那個類或其父類或祖先有__new__方法。

      ?

    1 2 3 4 5 6 7 8 9 10 11 12 class another(object): def __new__(cls,*args,**kwargs): print("newano") return object.__new__(cls, *args, **kwargs) class display(object): def __init__(self, *args, **kwargs): print("init") def __new__(cls, *args, **kwargs): print("newdis") print(type(cls)) return another.__new__(cls, *args, **kwargs) a=display()

      上面的輸出是:

      ?

    1 2 3 4 newdis <class 'type'> newano init

      所有我們發現__new__和__init__就像這麼一個關系,__init__提供生產的原料self(但並不保證這個原料來源正宗,像上面那樣它用的是另一個不相關的類的__new__方法類得到這個實例),而__init__就用__new__給的原料來完善這個對象(盡管它不知道這些原料是不是正宗的)

    1. 上一頁:
    2. 下一頁:
    Copyright © 程式師世界 All Rights Reserved