2010-06-28 85 views
26

我明白__init____new__是如何工作的。 我想知道是否有什麼__init__可以做到__new__不可以?Python:總是使用__new__而不是__init__?

即可以使用__init__通過以下方式代替:

class MySubclass(object): 
    def __new__(cls, *args, **kwargs): 
     self = super(MySubclass, cls).__new__(cls, *args, **kwargs) 
     // Do __init__ stuff here 
     return self 

我問,因爲我想使Python OO這方面適合我的頭好。

+0

[爲什麼在一個類中定義了'\ _ \ _ new__'和'\ _ \ _ init__'](http:// stackoverflow。在這個主題上的老問題:[Python的使用\ _ \ _ new__和\ _ \ _ init__?](http:/ /問題/ 2017876/Why-defined-new-and-init-all-in-a-class) – 2012-08-03 05:51:18

+0

/stackoverflow.com/questions/674304/pythons-use-of-new-and-init) – 2010-06-28 10:15:01

回答

4

guido's post(感謝@ fraca7)一個可能的答案:

例如,泡菜模塊中,__new__使用反序列化對象時創建實例。在這種情況下,會創建實例,但不會調用__init__方法。

還有其他相似的答案?


我接受這個答案爲「是」我自己的問題:

我想知道是否有任何__init__能做到這一點__new__不能?

是的,與__new__不同,您在取出過程中不會執行在__init__方法中執行的操作。 __new__無法作出此區分。

2

好吧,在谷歌上找__new__ vs __init__告訴我this

長話短說,__new__返回一個新的對象實例,而__init__什麼也沒有返回,只是初始化類成員。

編輯:要真正回答你的問題,你應該永遠不需要重寫__new__,除非你是不可變類型的子類。

+1

Guido最近談到: http://python-history.blogspot.com/2010/06/inside-story- on-new-style-classes.html – fraca7 2010-06-28 10:38:15

+2

還有其他一些使用'__new__'的原因,例如flyweight模式。 – 2010-06-28 11:29:39

21

因此,一個班級的班級通常是type,當您撥打Class()時,的Class的班級處理該班級。我相信type.__call__()實現或多或少是這樣的:

def __call__(cls, *args, **kwargs): 
    # should do the same thing as type.__call__ 
    obj = cls.__new__(cls, *args, **kwargs) 
    if isinstance(obj, cls): 
     obj.__init__(*args, **kwargs) 
    return obj 

直接回答你的問題是否定的,事情__init__()可以做的(變化/「初始化」指定實例)是的東西一個子集, __new__()可以做(創建或以其他方式選擇它想要的任何對象,在對象返回之前對該對象執行任何操作)。

但是,使用這兩種方法都很方便。使用__init__()更簡單(它不需要創建任何東西,它不需要返回任何東西),我相信最好的做法是始終使用__init__(),除非您有特定的理由使用__new__()

+0

對我而言,這並沒有真正回答OP的問題。你說過「__init __()'可以做的事情是'__new __()'可以做的事情的一個子集」,但這正是OP的觀點,不是嗎?如果這句話是真的,那麼'__init __()'可以被安全棄用,因爲它可以做的任何事情'__new __()'都可以做到。 – Ray 2017-08-17 10:22:37

+0

@Ray **你的結論沒有遵循你的前提。**雖然這句話*表面上是真的,但是'__init __()'不能由於所有顯而易見的原因被安全棄用 - 特別是**(A)**需要保持與現有Python生態系統的向後兼容性*和* **(B)** __new __()'API(其設計要求明確返回一個實例)與'__init __()'的合約脆弱性API(其設計沒有這樣的限制)。 '__new __()'會導致API違規,這是不好的; '__init __()'不*,這很好。 – 2018-02-08 04:55:51

相關問題