国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > Python > 正文

Python中__new__與__init__方法的區(qū)別詳解

2020-01-04 19:17:08
字體:
供稿:網(wǎng)友

這篇文章主要介紹了Python中__new__與__init__方法的區(qū)別,是Python學(xué)習(xí)中的基礎(chǔ)知識,需要的朋友可以參考下

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

新式類跟經(jīng)典類的差別主要是以下幾點(diǎn):

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

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

例子:

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

 

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

新式類繼承搜索程序是寬度優(yōu)先

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

 

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

3. 新式類增加了__slots__內(nèi)置屬性, 可以把實(shí)例屬性的種類鎖定到__slots__規(guī)定的范圍之中。

4. 新式類增加了__getattribute__方法

5.新式類內(nèi)置有__new__方法而經(jīng)典類沒有__new__方法而只有__init__方法

注意:Python 2.x中默認(rèn)都是經(jīng)典類,只有顯式繼承了object才是新式類

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

例如:

 

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

會發(fā)現(xiàn)在2.x下沒有__new__方法而3.x下有。

接下來說下__new__方法和__init__的區(qū)別:

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

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

 

 
  1. class display(object): 
  2. def __init__(self, *args, **kwargs): 
  3. print("init"
  4. def __new__(cls, *args, **kwargs): 
  5. print("new"
  6. print(type(cls)) 
  7. return object.__new__(cls, *args, **kwargs)  
  8. a=display() 

運(yùn)行上述代碼會得到如下輸出:

 

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

因此我們可以得到如下結(jié)論:

在實(shí)例創(chuàng)建過程中__new__方法先于__init__方法被調(diào)用,它的第一個參數(shù)類型為type。

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

于是我們可以發(fā)現(xiàn),實(shí)際上可以使用其它類的__new__方法類得到這個實(shí)例,只要那個類或其父類或祖先有__new__方法。

 

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

上面的輸出是:

 

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

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

發(fā)表評論 共有條評論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 萍乡市| 河津市| 宝丰县| 寻乌县| 郎溪县| 延川县| 吴川市| 长沙市| 黄平县| 上饶市| 房山区| 方山县| 宾阳县| 雅江县| 本溪市| 阿坝| 红河县| 多伦县| 永登县| 达州市| 江西省| 吉林市| 永定县| 锡林浩特市| 青岛市| 平乐县| 凤山市| 尼勒克县| 大渡口区| 邢台县| 辽中县| 通州市| 凌源市| 大兴区| 松潘县| 诸暨市| 惠州市| 平泉县| 白山市| 海伦市| 镇雄县|