python--__init__()方法和__new__()方法

  這兩個方法是python類中的基本方法,常常會在一些面試中問到。即使沒有要面試之類的,學習一下其內部的原理和使用也是有必要的。python

 

首先區分一下這兩個方法:

  • __init__:初始化方法
  • __new__:構造函數

 

 

  • __init__:實例方法
  • __new__:靜態方法

 

  • __new__:建立實例,並返回cls實例,也就是init方法的第一參數self
  • __init__:在new建立實例對象後調用,self表明建立的這個實例對象,init設置對象屬性的初始值,所以是實例方法,並不返回值

 


一點小插曲:面試

  __new__方法在繼承自object的新式類中才有,說到這裏,提一下新式類與經典類:函數

    • object爲全部類的基類
    • 從object繼承得來的類稱爲新式類,沒有繼承object的爲經典類
    • 新式類和經典類的一個常見的差異在於其繼承父類的方式,新式類的搜索方式爲廣度優先,而經典類爲深度優先。(固然還有其餘的,有興趣再查一下)
    • python2默認經典類,python3默認新式類,python2能夠顯示繼承object(class A(object))

 

1 def __init__(self, *args, **kwargs):
2     pass
3 
4 def __new__(cls, *args, **kwargs):
5     return object.__new__(cls, *args, **kwargs) 

 

建立實例對象的過程:

  上面給出了初始化方法和構造函數,能夠看到初始化方法沒有返回值,而構造函數有返回值。學習

  首先,在建立一個類的實例時,先調用構造方法(new),他接受當前正在實例化的類做爲第一參數(cls),而後返回建立產生的實例,給__init__方法的第一參數self,讓其進行初始值的設置。
  咱們在初學時常常會見到init方法,可是不多見到new方法,這裏解釋一下,new方法常常不被重寫,python中默認調用了父類的new,若是父類沒有就繼續上溯,直到object的new方法。(既然說是重寫了,那麼就必定在他的祖先類中有這個方法,最根本的就是object類,他是全部新式類的基類)spa

  文字也許看的有點懵,那就舉個例子:code

 1 class A(object):
 2     """docstring for A"""
 3     def __init__(self, *args, **kwargs):
 4         print("init ",self.__class__)
 5 
 6     def __new__(cls, *args,**kwargs):
 7         print("new ",cls)
 8         return object.__new__(cls, *args,**kwargs)
 9 
10 a = A()

結果輸出:

  new <class '__main__.A'>
  init <class '__main__.A'>對象

  上面的類中定義了init和new,在建立實例對象a時,代碼執行只是通過了init的函數定義部分,把這個函數名存在記憶當中,須要用時再調用。而後到了new方法時,接受當前這個類給第一參數cls,來建立對象。建立好對象以後,這個對象的屬性方法還什麼都沒有,如今就返回這個對象(也就是init中的self),來給init來初始化一些內容。若是構造函數並無返回這個類的對象,那麼init方法也就不會被調用。這也符合了上面的輸出結果,先輸出的new方法的內容,後執行的init方法中的輸出。blog

  沒有返回這個類的對象能夠是根本就沒有返回值,也多是返回的對象並非當前的類的對象,下面會對應舉兩個例子:繼承

 

  上面這張截圖中,我把上面代碼的new方法返回刪掉了,如今就只調用的new方法,而沒有到init方法內部去。如今這種狀況就是new沒有返回對象,init方法的第一參數self就沒有接收到要初始化的對象,所以並不執行。string

 

 1 class A(object):
 2     """docstring for A"""
 3     pass
 4 
 5 class B(A):
 6     """docstring for B"Af __init__(self, arg):    """
 7     def __init__(self):
 8         print("init ",self.__class__)
 9 
10     def __new__(cls):
11         print("new ",cls)
12         return object.__new__(A) # 返回的是A的對象,並非當前類中的實例對象,因此不能調用init方法

  上面這段代碼是說構造函數有返回值,但不是當前類的實例對象,所以也不能調用初始化方法。

相關文章
相關標籤/搜索