Python函數(shù)__new__及__init__作用及區(qū)別解析
【同】
二者均是Python面向?qū)ο笳Z言中的函數(shù),__new__比較少用,__init__則用的比較多。
【異】
__new__是在實(shí)例創(chuàng)建之前被調(diào)用的,因?yàn)樗娜蝿?wù)就是創(chuàng)建實(shí)例然后返回該實(shí)例對象,是個靜態(tài)方法。__init__是當(dāng)實(shí)例對象創(chuàng)建完成后被調(diào)用的,然后設(shè)置對象屬性的一些初始值,通常用在初始化一個類實(shí)例的時候。是一個實(shí)例方法。
也就是:__new__先被調(diào)用,__init__后被調(diào)用,__new__的返回值(實(shí)例)將傳遞給__init__方法的第一個參數(shù),然后__init__給這個實(shí)例設(shè)置一些參數(shù)。

===》》》
【一些說明】
1、繼承自object的新式類才有__new__
2、__new__至少要有一個參數(shù)cls,代表當(dāng)前類,此參數(shù)在實(shí)例化時由Python解釋器自動識別
3、__new__必須要有返回值,返回實(shí)例化出來的實(shí)例,這點(diǎn)在自己實(shí)現(xiàn)__new__時要特別注意,可以return父類(通過super(當(dāng)前類名, cls))__new__出來的實(shí)例,或者直接是object的__new__出來的實(shí)例
4、__init__有一個參數(shù)self,就是這個__new__返回的實(shí)例,__init__在__new__的基礎(chǔ)上可以完成一些其它初始化的動作,__init__不需要返回值
5、如果__new__創(chuàng)建的是當(dāng)前類的實(shí)例,會自動調(diào)用__init__函數(shù),通過return語句里面調(diào)用的__new__函數(shù)的第一個參數(shù)是 cls 來保證是當(dāng)前類實(shí)例,如果是其他類的類名,;那么實(shí)際創(chuàng)建返回的就是其他類的實(shí)例,其實(shí)就不會調(diào)用當(dāng)前類的__init__函數(shù),也不會調(diào)用其他類的__init__函數(shù)。
6、在定義子類時沒有重新定義__new__()時,Python默認(rèn)是調(diào)用該類的直接父類的__new__()方法來構(gòu)造該類的實(shí)例,如果該類的父類也沒有重寫__new__(),那么將一直按此規(guī)矩追溯至object的__new__()方法,因?yàn)閛bject是所有新式類的基類。
7、而如果子類中重寫了__new__()方法,那么你可以自由選擇任意一個的其他的新式類(必定要是新式類,只有新式類必定都有__new__(),因?yàn)樗行率筋惗际莖bject的后代,而經(jīng)典類則沒有__new__()方法)的__new__()方法來制造實(shí)例,包括這個新式類的所有前代類和后代類,只要它們不會造成遞歸死循環(huán)。反正肯定不能調(diào)用自己的__new__,這肯定是死循環(huán)。
8、對于子類的__init__,其調(diào)用規(guī)則跟__new__是一致的,當(dāng)然如果子類和父類的__init__函數(shù)都想調(diào)用,可以在子類的__init__函數(shù)中加入對父類__init__函數(shù)的調(diào)用。
9、我們在使用時,盡量使用__init__函數(shù),不要去自定義__new__函數(shù),因?yàn)檫@兩者在繼承派生時的特性還是很不一樣的。
10、將類比作制造商,__new__方法就是前期的原材料購買環(huán)節(jié),__init__方法就是在有原材料的基礎(chǔ)上,加工,初始化商品環(huán)節(jié)
【__init__方法】

【__new__方法】
__new__方法接受的參數(shù)雖然也是和__init__一樣,但__init__是在類實(shí)例創(chuàng)建之后調(diào)用,而 __new__方法正是創(chuàng)建這個類實(shí)例的方法。
===》
具體的執(zhí)行邏輯:
1. p = Person(name, age)
2. 首先執(zhí)行使用name和age參數(shù)來執(zhí)行Person類的__new__方法,這個__new__方法會返回Person類的一個實(shí)例(通常情況下是使用 super(Persion, cls).__new__(cls, ... ...) 這樣的方式),
3. 然后利用這個實(shí)例來調(diào)用類的__init__方法,上一步里面__new__產(chǎn)生的實(shí)例也就是 __init__里面的的 self。
所以,__init__ 和 __new__ 最主要的區(qū)別在于:
1.__init__ 通常用于初始化一個新實(shí)例,控制這個初始化的過程,比如添加一些屬性, 做一些額外的操作,發(fā)生在類實(shí)例被創(chuàng)建完以后。它是實(shí)例級別的方法。
2.__new__ 通常用于控制生成一個新實(shí)例的過程。它是類級別的方法。
【__new__的作用】
依照Python官方文檔的說法,__new__方法主要是當(dāng)你繼承一些不可變的class時(比如int, str, tuple), 提供給你一個自定義這些類的實(shí)例化過程的途徑。還有就是實(shí)現(xiàn)自定義的metaclass。
首先我們來看一下第一個功能,具體我們可以用int來作為一個例子:
假如我們需要一個永遠(yuǎn)都是正數(shù)的整數(shù)類型,通過集成 int,我們可能會寫出這樣的代碼。

但運(yùn)行后會發(fā)現(xiàn),結(jié)果根本不是我們想的那樣,我們?nèi)稳坏玫搅?3。這是因?yàn)閷τ趇nt這種 不可變的對象,我們只有重載它的__new__方法才能起到自定義的作用。
這是修改后的代碼:

通過重載__new__方法,我們實(shí)現(xiàn)了需要的功能。
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- 詳解Python中的__init__和__new__
- python中的__init__ 、__new__、__call__小結(jié)
- Python中__init__和__new__的區(qū)別詳解
- Python中__new__與__init__方法的區(qū)別詳解
- 淺談python中的__init__、__new__和__call__方法
- 深入理解Python中的 __new__ 和 __init__及區(qū)別介紹
- Python中__new__和__init__的區(qū)別與聯(lián)系
- Python中class內(nèi)置方法__init__與__new__作用與區(qū)別解析
- python __init__與 __new__的區(qū)別
- 詳解Python中__new__和__init__的區(qū)別與聯(lián)系
- python中__new__和__init__的實(shí)現(xiàn)
相關(guān)文章
Python數(shù)據(jù)結(jié)構(gòu)之翻轉(zhuǎn)鏈表
這篇文章主要介紹了Python數(shù)據(jù)結(jié)構(gòu)之翻轉(zhuǎn)鏈表的相關(guān)資料,需要的朋友可以參考下2017-02-02
Python中yield關(guān)鍵字及與return的區(qū)別詳解
這篇文章主要介紹了Python中yield關(guān)鍵字及與return的區(qū)別詳解,帶有 yield 的函數(shù)在 Python 中被稱之為 generator生成器,比如列表所有數(shù)據(jù)都在內(nèi)存中,如果有海量數(shù)據(jù)的話將會非常耗內(nèi)存,想要得到龐大的數(shù)據(jù),又想讓它占用空間少,那就用生成器,需要的朋友可以參考下2023-08-08
wxPython定時器wx.Timer簡單應(yīng)用實(shí)例
這篇文章主要介紹了wxPython定時器wx.Timer簡單應(yīng)用,實(shí)例分析了Python使用wxPython創(chuàng)建窗口應(yīng)用程序及定時器的相關(guān)使用技巧,需要的朋友可以參考下2015-06-06

