Ich habe kürzlich irgendwo gelesen, dass der spezielle Wert None
in Python ein Singleton-Objekt seiner eigenen Klasse ist, speziell NoneType
. Dies erklärt eine Menge, da die meisten Fehler, die None
in Python betreffen, AttributeError
s statt eines speziellen "NoneError" oder etwas erzeugen.
Da all diese AttributeErrors
die Attribute widerspiegelten, die NoneType
fehlten, war ich fasziniert von den Attributen, die NoneType
hat , falls vorhanden.
Ich habe mich entschieden, in diese NoneType
zu schauen und mehr darüber zu erfahren. Ich habe immer den besten Weg gefunden, etwas über ein neues Sprachfeature zu lernen, es zu benutzen, also habe ich versucht, NoneType
in IDLE zu instanziieren:
Dies führte zu einem Fehler:
%Vor% Verwirrt habe ich None
inspiziert, um zu sehen, ob ich den korrekten Typnamen bekommen habe. Sicher genug,
Nun sehr verwirrt, habe ich eine schnelle Google-Suche gemacht. Dies enthüllte, dass aus irgendeinem Grund NoneType irgendwie in Python 3 entfernt wurde.
Nun, ich, ha ha! Ich kann das umgehen, indem ich den Typ von None
in einer Variablen speichere, da Klassen Objekte in Python sind. Dies schien arbeiten:
Und als ich n druckte, bekam ich ziemlich genau das, was ich erwartet hatte:
%Vor%Aber dann ist das passiert:
%Vor%Und:
%Vor% Meine Variable n
IS None
. Nicht nur der gleiche Typ wie None
. Es ist None
. Das habe ich nicht erwartet.
Ich habe versucht, mit dis
mehr Informationen über NoneType
zu erhalten, aber als ich
Es hat keine Ausgabe erzeugt.
Ich habe dann versucht, die Methode __new__
zu untersuchen, die mehrere Benutzer in den Kommentaren erwähnt haben:
Weitere Fehler.
Hier sind meine Fragen:
n
genau dasselbe Objekt wie None
? n
genau dasselbe Objekt ist wie None
? Warum ist n
genau dasselbe Objekt wie None
?
Die C-Implementierung behält eine Singleton-Instanz bei. NoneType.__new__
gibt die Singleton-Instanz zurück.
Warum wurde die Sprache so entworfen, dass n das exakt gleiche Objekt ist wie None
?
Wenn es keine Singleton-Instanz gab, konnten Sie sich nicht auf den Check x is None
verlassen, da der Operator is
auf der Identität basiert. Obwohl None == None
auch True
ist, ist es möglich, dass x == None
be True
ist, wenn x
nicht tatsächlich None
ist. Siehe diese Antwort für ein Beispiel.
Wie würde man dieses Verhalten in Python überhaupt umsetzen?
Sie können dieses Muster implementieren, indem Sie __new__
überschreiben. Hier ist ein einfaches Beispiel:
Ausgabe:
s1 ist s2: Wahres
ID (s1): 4506243152
ID (s2): 4506243152
Natürlich macht es dieses einfache Beispiel nicht unmöglich eine zweite Instanz zu erstellen.
Andere Antworten beschreiben, wie man __new__
benutzt, um ein Singleton zu implementieren, aber so ist None tatsächlich nicht implementiert (zumindest in cPython habe ich keine anderen Implementierungen betrachtet).
Der Versuch, eine Instanz von None bis type(None)()
zu erstellen, ist speziell umkreist und führt zum Aufruf von folgende C-Funktion :
Und Py_RETURN_NONE
ist hier definiert :
Vergleichen Sie dies mit der Funktion, die ein normales Python-Objekt erstellt :
%Vor% Wenn Sie ein normales Objekt erstellen, wird Speicher für das Objekt zugewiesen und initialisiert. Wenn Sie versuchen, eine neue Instanz von None
zu erstellen, erhalten Sie lediglich einen Verweis auf die bereits vorhandene _Py_NoneStruct
. Deshalb ist jede Referenz auf None
, egal was du tust, genau dasselbe Objekt.
Der NoneType überschreibt __new__
, die immer denselben Singleton zurückgeben. Der Code ist tatsächlich in C geschrieben , so dass dis
nicht helfen kann, aber konzeptionell Es ist einfach so.
Es ist einfacher, mit nur einer None-Instanz zu arbeiten. Sie sind alle gleich.
Durch Überschreiben von __new__
... z. B.
Warum ist das exakt gleiche Objekt wie Keines?
Viele unveränderliche Objekte in Python sind interniert , einschließlich None
, kleinere Ints und viele Strings.
Demo:
%Vor%Warum wurde die Sprache entworfen? so dass n das exakt gleiche Objekt wie None ist?
Siehe oben - Geschwindigkeit, Effizienz, Mangel an Mehrdeutigkeit und Speichernutzung unter anderen Gründen, um unveränderliche Objekte zu internieren.
Wie würde man überhaupt? Implementieren Sie dieses Verhalten in Python?
Unter anderem können Sie __new__
überschreiben, um dasselbe Objekt zurückzugeben:
Für Zeichenfolgen können Sie intern auf Python 2 oder sys.intern auf Python 3
Tags und Links python singleton python-3.x python-internals nonetype