1. 程式人生 > 程式設計 >Python函式__new__及__init__作用及區別解析

Python函式__new__及__init__作用及區別解析

【同】

  二者均是Python面嚮物件語言中的函式,__new__比較少用,__init__則用的比較多。

【異】

__new__是在例項建立之前被呼叫的,因為它的任務就是建立例項然後返回該例項物件,是個靜態方法。__init__是當例項物件建立完成後被呼叫的,然後設定物件屬性的一些初始值,通常用在初始化一個類例項的時候。是一個例項方法。

也就是:__new__先被呼叫,__init__後被呼叫,__new__的返回值(例項)將傳遞給__init__方法的第一個引數,然後__init__給這個例項設定一些引數。

Python函式__new__及__init__作用及區別解析

===》》》Python函式__new__及__init__作用及區別解析

【一些說明】

1、繼承自object的新式類才有__new__

2、__new__至少要有一個引數cls,代表當前類,此引數在例項化時由Python直譯器自動識別

3、__new__必須要有返回值,返回例項化出來的例項,這點在自己實現__new__時要特別注意,可以return父類(通過super(當前類名,cls))__new__出來的例項,或者直接是object的__new__出來的例項

4、__init__有一個引數self,就是這個__new__返回的例項,__init__在__new__的基礎上可以完成一些其它初始化的動作,__init__不需要返回值

5、如果__new__建立的是當前類的例項,會自動呼叫__init__函式,通過return語句裡面呼叫的__new__函式的第一個引數是 cls 來保證是當前類例項,如果是其他類的類名,;那麼實際建立返回的就是其他類的例項,其實就不會呼叫當前類的__init__函式,也不會呼叫其他類的__init__函式。

6、在定義子類時沒有重新定義__new__()時,Python預設是呼叫該類的直接父類的__new__()方法來構造該類的例項,如果該類的父類也沒有重寫__new__(),那麼將一直按此規矩追溯至object的__new__()方法,因為object是所有新式類的基類。

7、而如果子類中重寫了__new__()方法,那麼你可以自由選擇任意一個的其他的新式類(必定要是新式類,只有新式類必定都有__new__(),因為所有新式類都是object的後代,而經典類則沒有__new__()方法)的__new__()方法來製造例項,包括這個新式類的所有前代類和後代類,只要它們不會造成遞迴死迴圈。反正肯定不能呼叫自己的__new__,這肯定是死迴圈。

8、對於子類的__init__,其呼叫規則跟__new__是一致的,當然如果子類和父類的__init__函式都想呼叫,可以在子類的__init__函式中加入對父類__init__函式的呼叫。

9、我們在使用時,儘量使用__init__函式,不要去自定義__new__函式,因為這兩者在繼承派生時的特性還是很不一樣的。

10、將類比作製造商,__new__方法就是前期的原材料購買環節,__init__方法就是在有原材料的基礎上,加工,初始化商品環節

【__init__方法】

Python函式__new__及__init__作用及區別解析

【__new__方法】

__new__方法接受的引數雖然也是和__init__一樣,但__init__是在類例項建立之後呼叫,而 __new__方法正是建立這個類例項的方法。

Python函式__new__及__init__作用及區別解析 ===》Python函式__new__及__init__作用及區別解析

具體的執行邏輯:

1. p = Person(name,age)

2. 首先執行使用name和age引數來執行Person類的__new__方法,這個__new__方法會返回Person類的一個例項(通常情況下是使用 super(Persion,cls).__new__(cls,... ...) 這樣的方式),

3. 然後利用這個例項來呼叫類的__init__方法,上一步裡面__new__產生的例項也就是 __init__裡面的的 self。

所以,__init__ 和 __new__ 最主要的區別在於:

1.__init__ 通常用於初始化一個新例項,控制這個初始化的過程,比如新增一些屬性, 做一些額外的操作,發生在類例項被建立完以後。它是例項級別的方法。

2.__new__ 通常用於控制生成一個新例項的過程。它是類級別的方法。

【__new__的作用】

依照Python官方文件的說法,__new__方法主要是當你繼承一些不可變的class時(比如int,str,tuple), 提供給你一個自定義這些類的例項化過程的途徑。還有就是實現自定義的metaclass。

首先我們來看一下第一個功能,具體我們可以用int來作為一個例子:

假如我們需要一個永遠都是正數的整數型別,通過整合 int,我們可能會寫出這樣的程式碼。

Python函式__new__及__init__作用及區別解析

但執行後會發現,結果根本不是我們想的那樣,我們任然得到了-3。這是因為對於int這種 不可變的物件,我們只有過載它的__new__方法才能起到自定義的作用。

這是修改後的程式碼:

Python函式__new__及__init__作用及區別解析

通過過載__new__方法,我們實現了需要的功能。

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支援我們。