Gibt es einen Unterschied zwischen ==
und is
in Python?
Ja, sie haben einen sehr wichtigen Unterschied.
==
: auf Gleichheit prüfen - Die Semantik lautet, dass äquivalente Objekte (die nicht unbedingt dasselbe Objekt sind) als gleich getestet werden. Wie die Dokumentation sagt :
Die Operatoren <,>, ==,> =, <= und! = Vergleichen die Werte zweier Objekte.
is
: Identitätsprüfung - Die Semantik lautet, dass das Objekt (wie im Speicher gespeichert) das Objekt ist. Wieder heißt es in der Dokumentation :
Die Betreiber is
und is not
Test für die Objektidentität: x is y
ist wahr , wenn und nur wenn x
und y
dasselbe Objekt sind. Die Objektidentität wird mit der id()
Funktion ermittelt. x is not y
ergibt den inversen Wahrheitswert.
Somit ist die Überprüfung auf Identität dieselbe wie die Überprüfung auf die Gleichheit der IDs der Objekte. Das ist,
a is b
ist das gleiche wie:
id(a) == id(b)
Wo id
ist die eingebaute Funktion, die eine Ganzzahl zurückgibt, die "garantiert unter gleichzeitig vorhandenen Objekten eindeutig ist" (siehe help(id)
) und wo a
und b
sind beliebige Objekte.
Andere Verwendungshinweise
Sie sollten diese Vergleiche für ihre Semantik verwenden. Verwenden Sie is
diese Option , um die Identität und ==
die Gleichheit zu überprüfen.
Im Allgemeinen is
überprüfen wir daher die Identität. Dies ist normalerweise nützlich, wenn wir nach einem Objekt suchen, das nur einmal im Speicher vorhanden sein sollte und in der Dokumentation als "Singleton" bezeichnet wird.
Anwendungsfälle für is
umfassen:
None
- Aufzählungswerte (bei Verwendung von Aufzählungen aus dem Aufzählungsmodul)
- in der Regel Module
- normalerweise Klassenobjekte, die aus Klassendefinitionen resultieren
- normalerweise Funktionsobjekte, die sich aus Funktionsdefinitionen ergeben
- alles andere, was nur einmal im Speicher existieren sollte (alle Singletons im Allgemeinen)
- ein bestimmtes Objekt, das Sie nach Identität möchten
Übliche Anwendungsfälle für ==
:
- Zahlen, einschließlich Ganzzahlen
- Saiten
- Listen
- setzt
- Wörterbücher
- benutzerdefinierte veränderbare Objekte
- in den meisten Fällen andere eingebaute unveränderliche Objekte
Die allgemeine Verwendung Fall wieder, denn ==
ist das Objekt , das Sie möglicherweise nicht das sein wollen gleiche Objekt, sondern kann es eine sein Äquivalent ein
PEP 8 Richtungen
PEP 8, der offizielle Python-Styleguide für die Standardbibliothek, erwähnt außerdem zwei Anwendungsfälle füris
:
Vergleiche mit Singletons wie None
sollten immer mit is
oder
is not
niemals mit den Gleichheitsoperatoren durchgeführt werden.
Achten if x
Sie auch darauf, nicht zu schreiben, wenn Sie es wirklich meinen if x is not None
- z. B. wenn Sie testen, ob eine Variable oder ein Argument, das standardmäßig verwendet wird, None
auf einen anderen Wert gesetzt wurde. Der andere Wert hat möglicherweise einen Typ (z. B. einen Container), der in einem booleschen Kontext falsch sein kann!
Gleichheit aus Identität ableiten
Wenn dies is
zutrifft, kann normalerweise auf Gleichheit geschlossen werden. Wenn ein Objekt selbst ist, sollte es logischerweise als gleichwertig mit sich selbst getestet werden.
In den meisten Fällen ist diese Logik richtig, sie beruht jedoch auf der Implementierung der __eq__
speziellen Methode. Wie die Dokumente sagen,
Das Standardverhalten für den Gleichheitsvergleich ( ==
und !=
) basiert auf der Identität der Objekte. Daher führt der Gleichheitsvergleich von Instanzen mit derselben Identität zu Gleichheit, und der Gleichheitsvergleich von Instanzen mit unterschiedlichen Identitäten führt zu Ungleichheit. Eine Motivation für dieses Standardverhalten ist der Wunsch, dass alle Objekte reflexiv sein sollten (dh x ist y impliziert x == y).
und im Interesse der Konsistenz empfiehlt:
Der Gleichstellungsvergleich sollte reflexiv sein. Mit anderen Worten, identische Objekte sollten gleich sein:
x is y
impliziert x == y
Wir können sehen, dass dies das Standardverhalten für benutzerdefinierte Objekte ist:
>>> class Object(object): pass
>>> obj = Object()
>>> obj2 = Object()
>>> obj == obj, obj is obj
(True, True)
>>> obj == obj2, obj is obj2
(False, False)
Das Kontrapositive ist normalerweise auch wahr - wenn etwas als nicht gleich getestet wird, können Sie normalerweise schließen, dass es nicht dasselbe Objekt ist.
Da Gleichheitstests angepasst werden können, gilt diese Schlussfolgerung nicht immer für alle Typen.
Eine Ausnahme
Eine bemerkenswerte Ausnahme ist nan
- es testet immer als nicht gleich sich selbst:
>>> nan = float('nan')
>>> nan
nan
>>> nan is nan
True
>>> nan == nan # !!!!!
False
Das Überprüfen der Identität kann viel schneller sein als das Überprüfen der Gleichheit (was möglicherweise eine rekursive Überprüfung der Mitglieder erfordert).
Gleichheit kann jedoch nicht ersetzt werden, wenn Sie möglicherweise mehr als ein Objekt als gleichwertig finden.
Beachten Sie, dass beim Vergleich der Gleichheit von Listen und Tupeln davon ausgegangen wird, dass die Identität von Objekten gleich ist (da dies eine schnelle Überprüfung ist). Dies kann zu Widersprüchen führen, wenn die Logik inkonsistent ist - wie für nan
:
>>> [nan] == [nan]
True
>>> (nan,) == (nan,)
True
Eine warnende Geschichte:
Die Frage versucht, is
ganze Zahlen zu vergleichen. Sie sollten nicht davon ausgehen, dass eine Instanz einer Ganzzahl dieselbe Instanz ist wie eine, die von einer anderen Referenz erhalten wurde. Diese Geschichte erklärt warum.
Ein Kommentator hatte Code, der sich auf die Tatsache stützte, dass kleine Ganzzahlen (-5 bis einschließlich 256) in Python Singletons sind, anstatt auf Gleichheit zu prüfen.
Wow, das kann zu heimtückischen Fehlern führen. Ich hatte einen Code, der überprüfte, ob a b ist, was wie gewünscht funktionierte, da a und b normalerweise kleine Zahlen sind. Der Fehler trat erst heute nach sechs Monaten in der Produktion auf, weil a und b endlich groß genug waren, um nicht zwischengespeichert zu werden. - gwg
Es hat in der Entwicklung funktioniert. Es kann einige Unittests bestanden haben.
Und es funktionierte in der Produktion - bis der Code nach einer ganzen Zahl größer als 256 suchte und zu diesem Zeitpunkt in der Produktion fehlschlug.
Dies ist ein Produktionsfehler, der bei der Codeüberprüfung oder möglicherweise mit einem Style-Checker aufgetreten sein könnte.
Lassen Sie mich betonen: Verwenden Sie nicht is
, um ganze Zahlen zu vergleichen.
echo 'import sys;tt=sys.argv[1];print(tt is "foo", tt == "foo", id(tt)==id("foo"))'| python3 - foo
Ausgabe :False True False
.