Die Frage, die ich stellen werde, scheint ein Duplikat von Pythons Verwendung von __new__ und __init__ zu sein. Trotzdem ist mir immer noch unklar, was genau der praktische Unterschied zwischen __new__
und __init__
ist.
Bevor Sie mir sagen, dass dies __new__
zum Erstellen von Objekten und __init__
zum Initialisieren von Objekten dient, lassen Sie mich klar sein: Ich verstehe das. Tatsächlich ist diese Unterscheidung für mich ganz natürlich, da ich Erfahrung in C ++ habe, wo wir eine neue Platzierung haben , die in ähnlicher Weise die Objektzuweisung von der Initialisierung trennt.
Das Python C API-Tutorial erklärt es folgendermaßen:
Das neue Mitglied ist für das Erstellen (im Gegensatz zum Initialisieren) von Objekten des Typs verantwortlich. Es wird in Python als
__new__()
Methode verfügbar gemacht. ... Ein Grund für die Implementierung einer neuen Methode besteht darin, die Anfangswerte der Instanzvariablen sicherzustellen .
Also, ja - ich verstehe , was es __new__
tut, aber trotzdem verstehe ich immer noch nicht, warum es in Python nützlich ist. Das angegebene Beispiel besagt, dass __new__
dies nützlich sein kann, wenn Sie "die Anfangswerte von Instanzvariablen sicherstellen" möchten. Ist das nicht genau das, was __init__
wir tun werden?
Im C API-Tutorial wird ein Beispiel gezeigt, in dem ein neuer Typ ("Noddy" genannt) erstellt und die __new__
Funktion des Typs definiert wird. Der Noddy-Typ enthält ein Zeichenfolgenelement mit dem Namen first
, und dieses Zeichenfolgenelement wird wie folgt mit einer leeren Zeichenfolge initialisiert:
static PyObject * Noddy_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
.....
self->first = PyString_FromString("");
if (self->first == NULL)
{
Py_DECREF(self);
return NULL;
}
.....
}
Beachten Sie, dass __new__
wir ohne die hier definierte Methode verwenden müssten PyType_GenericNew
, die einfach alle Instanzvariablenelemente auf NULL initialisiert. Der einzige Vorteil der __new__
Methode besteht darin, dass die Instanzvariable im Gegensatz zu NULL als leere Zeichenfolge beginnt. Aber warum ist das jemals nützlich, denn wenn wir sicherstellen wollten, dass unsere Instanzvariablen auf einen Standardwert initialisiert werden, hätten wir das einfach in der __init__
Methode tun können ?
__new__
ist kein Boilerplate, da sich das Boilerplate nie ändert. Manchmal müssen Sie diesen bestimmten Code durch etwas anderes ersetzen.