2010-06-28 11 views
26

Capisco come funzionano entrambe le funzioni __init__ e __new__. Mi chiedo se non c'è nulla che lo può fare che lo __new__ non può?Python: usa sempre __new__ invece di __init__?

cioè può usare di __init__ è sostituito dal seguente schema:

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

sto chiedendo come mi piacerebbe fare questo aspetto della Python OO adattarsi meglio nella mia testa.

+0

possibile duplicato di [perché definito '\ _ \ _ new__' e '\ _ \ _ init__' tutto in una classe] (http: // stackoverflow.it/questions/2017876/why-defined-new-and-init-all-in-a-class) –

+0

Vecchia domanda su questo argomento: [L'uso di Python di \ _ \ _ new__ e \ _ \ _ init__?] (http://stackoverflow.com/questions/674304/pythons-use-of-new-and-init) –

risposta

4

Una possibile risposta da guido's post (grazie @ fraca7):

Ad esempio, nel modulo salamoia, __new__ viene utilizzato per creare istanze quando deserializzazione oggetti. In questo caso, vengono create istanze, ma il metodo __init__ non viene richiamato.

Altre risposte simili?


Sono accettare questa risposta come un 'sì' alla mia domanda:

Mi chiedo se c'è qualcosa __init__ può farlo __new__ non può?

Sì, a differenza __new__, le azioni che si mette nel metodo __init__ non verrà eseguita durante il processo di deserializzazione. __new__ non può fare questa distinzione.

2

Bene, cercando __new__ vs __init__ su google mi ha mostrato this.

In breve, __new__ restituisce una nuova istanza di oggetto, mentre __init__ non restituisce nulla e inizializza solo i membri della classe.

MODIFICA: per rispondere effettivamente alla domanda, non è mai necessario eseguire l'override di __new__ a meno che non si stia sottoclassi di tipi immutabili.

+1

Guido ne ha parlato recentemente: http://python-history.blogspot.com/2010/06/inside-story- on-new-style-classes.html – fraca7

+2

Esistono altri motivi per utilizzare '__new__', ad esempio il modello del peso mosca. –

21

Quindi, la classe di una classe è tipicamente type, e quando si chiama il metodo Class()__call__() sulla classe Class s' gestisce tale. Credo type.__call__() è implementato più o meno così:

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 

La risposta diretta alla sua domanda è no, le cose che __init__() può fare (cambio/"inizializzare" l'istanza specificata) è un sottoinsieme delle cose che __new__() può fare (creare o altrimenti selezionare qualsiasi oggetto che vuole, fare qualcosa per quell'oggetto che vuole prima che l'oggetto venga restituito).

È comunque utile disporre di entrambi i metodi. L'uso di __init__() è più semplice (non è necessario creare nulla, non deve restituire nulla) e credo sia preferibile utilizzare sempre __init__() a meno che non si abbia un motivo specifico per utilizzare __new__().

+0

Per me, questo in realtà non risponde alla domanda dell'OP. Hai detto che "le cose che' __init __() 'possono fare è un sottoinsieme delle cose che' __new __() 'può fare", ma questo è precisamente il punto dell'OP, non è vero? Se quella frase è vera, allora '__init __()' può essere tranquillamente deprecato, perché tutto ciò che può fare, '__new __()' può fare altrettanto bene. – Ray

+0

@Ray ** La tua conclusione non segue la tua premessa. ** Mentre quella frase * è * apparentemente vera, '__init __()' non può essere disapprovata in modo sicuro per tutte le ovvie ragioni - in particolare, ** (A) ** la necessità di preservare la compatibilità con l'esistente ecosistema Python * e * ** (B) ** la fragilità contrattuale dell'API '__new __()' (il cui design richiede che un'istanza sia restituita esplicitamente) rispetto a '__init __()' API (il cui design non impone tali vincoli). '__new __()' invita le violazioni API, il che è male; '__init __()' non * non *, che è buono. –

Problemi correlati