Wenn ein float
Objekt float()
geliefert wird, CPython * gibt es nur, ohne ein neues Objekt zu machen.
Dies kann in PyNumber_Float
zu sehen, wo das Objekt o
mit PyFloat_CheckExact
geprüft bestanden (die schließlich von float_new
genannt wird); wenn True
, es erhöht nur den Referenzzähler und gibt ihr:
if (PyFloat_CheckExact(o)) {
Py_INCREF(o);
return o;
}
Als Ergebnis der id
des Objekts gleich bleibt. So ist der Ausdruck
>>> float(0.0) is float(0.0)
reduziert sich auf:
>>> 0.0 is 0.0
Aber warum tut das gleiche True
? Nun, CPython
hat einige kleine Optimierungen.
In diesem Fall verwendet es das gleiche Objekt für die beiden Vorkommen von 0.0
in Ihrem Befehl, weil sie Teil von the same code
object sind (kurzer Haftungsausschluss: sie sind auf der gleichen logischen Linie); so wird der is
Test erfolgreich sein.
Dies kann weiter, wenn Sie float(0.0)
in getrennten Leitungen (oder begrenzt durch ;
) und dann Prüfung für Identität ausführen erhärtet werden:
a = float(0.0); b = float(0.0) # Python compiles these separately
a is b # False
Auf der anderen Seite, wenn ein int
(oder ein str
) geliefert wird, erstellt CPython ein neuesfloat
Objekt daraus und gibt das zurück. Dazu verwendet es PyFloat_FromDouble
bzw. PyFloat_FromString
.
Der Effekt ist, dass die zurückgegebenen Objekte in id
s unterscheiden (die Identitäten überprüft, mit is
):
# Python uses the same object representing 0 to the calls to float
# but float returns new float objects when supplied with ints
# Thereby, the result will be False
float(0) is float(0)
* Hinweis: Alle bisherigen erwähnten Verhalten für die Umsetzung gilt der Python in C
dh CPython
. Andere Implementierungen weisen möglicherweise ein anderes Verhalten auf. Kurz gesagt, nicht davon abhängen.
In Verbindung stehende: http://stackoverflow.com/questions/132988/is-there-a-difference-between-and-is-in-python – Elazar
Ihre Frage verdient eine Antwort, aber wenn Sie auf dieses Problem stoßen in echter Code, der Code ist wahrscheinlich fehlerhaft und sollte behoben werden. Es gibt (fast) keinen Grund, die Referenzidentität zwischen Schwimmern so zu testen. – Elazar
Die seltsame Sache ist, dass, obwohl ich dies reproduzieren kann, alle von 'id (0.0) ',' id (float (0.0)) 'und' id (float (0)) 'den gleichen Wert zurückgeben. ... Das heißt, der Wert ist der gleiche, wenn ich diese nacheinander in der interaktiven Shell ausfühle, aber wenn ich 'id (float (0.0)), id (float (0))' (als Tupel) mache dann unterscheiden sich die IDs. Irgendeine Erklärung? –