【同】html
兩者均是Python面嚮對象語言中的函數,__new__比較少用,__init__則用的比較多。函數
【異】spa
也就是: __new__先被調用,__init__後被調用,__new__的返回值(實例)將傳遞給__init__方法的第一個參數,而後__init__給這個實例設置一些參數。.net
===》》》3d
【一些說明】code
一、繼承自object的新式類纔有__new__htm
二、__new__至少要有一個參數cls,表明當前類,此參數在實例化時由Python解釋器自動識別對象
三、__new__必需要有返回值,返回實例化出來的實例,這點在本身實現__new__時要特別注意,能夠return父類(經過super(當前類名, cls))__new__出來的實例,或者直接是object的__new__出來的實例blog
四、__init__有一個參數self,就是這個__new__返回的實例,__init__在__new__的基礎上能夠完成一些其它初始化的動做,__init__不須要返回值繼承
五、若是__new__建立的是當前類的實例,會自動調用__init__函數,經過return語句裏面調用的__new__函數的第一個參數是 cls 來保證是當前類實例,若是是其餘類的類名,;那麼實際建立返回的就是其餘類的實例,其實就不會調用當前類的__init__函數,也不會調用其餘類的__init__函數。
六、在定義子類時沒有從新定義__new__()時,Python默認是調用該類的直接父類的__new__()方法來構造該類的實例,若是該類的父類也沒有重寫__new__(),那麼將一直按此規矩追溯至object的__new__()方法,由於object是全部新式類的基類。
七、而若是子類中重寫了__new__()方法,那麼你能夠自由選擇任意一個的其餘的新式類(一定要是新式類,只有新式類一定都有__new__(),由於全部新式類都是object的後代,而經典類則沒有__new__()方法)的__new__()方法來製造實例,包括這個新式類的全部前代類和後代類,只要它們不會形成遞歸死循環。反正確定不能調用本身的__new__,這確定是死循環。
八、對於子類的__init__,其調用規則跟__new__是一致的,固然若是子類和父類的__init__函數都想調用,能夠在子類的__init__函數中加入對父類__init__函數的調用。
九、咱們在使用時,儘可能使用__init__函數,不要去自定義__new__函數,由於這二者在繼承派生時的特性仍是很不同的。
十、將類比做製造商,__new__
方法就是前期的原材料購買環節,__init__
方法就是在有原材料的基礎上,加工,初始化商品環節
【__init__方法】
【__new__方法】
__new__方法接受的參數雖然也是和__init__同樣,但__init__是在類實例建立以後調用,而 __new__方法正是建立這個類實例的方法。
===》
具體的執行邏輯:
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,咱們可能會寫出這樣的代碼。
但運行後會發現,結果根本不是咱們想的那樣,咱們任然獲得了-3。這是由於對於int這種 不可變的對象,咱們只有重載它的__new__方法才能起到自定義的做用。
這是修改後的代碼:
經過重載__new__方法,咱們實現了須要的功能。
【牛客網上一道題】
※ __new__和__init__的區別,說法正確的是? (ABCD)
A. __new__是一個靜態方法,而__init__是一個實例方法
B. __new__方法會返回一個建立的實例,而__init__什麼都不返回
C. 只有在__new__返回一個cls的實例時,後面的__init__才能被調用
D. 當建立一個新實例時調用__new__,初始化一個實例時用__init__
【Reference】
一、https://my.oschina.net/kinegratii/blog/334968
二、https://www.cnblogs.com/suntp/p/6445286.html
三、https://my.oschina.net/liuyuantao/blog/747164