Mein Google-Fu hat mich gescheitert.
Sind in Python die folgenden zwei Tests auf Gleichheit gleichwertig?
n = 5
# Test one.
if n == 5:
print 'Yay!'
# Test two.
if n is 5:
print 'Yay!'
Gilt dies für Objekte, bei denen Sie Instanzen vergleichen würden (ein list
Mitspracherecht)?
Okay, diese Art beantwortet meine Frage:
L = []
L.append(1)
if L == [1]:
print 'Yay!'
# Holds true, but...
if L is [1]:
print 'Yay!'
# Doesn't.
So ==
testet Wert , bei dem is
überprüft, ob sie das gleiche Objekt sind?
echo 'import sys;tt=sys.argv[1];print(tt is "foo", tt == "foo", id(tt)==id("foo"))'| python3 - foo
Ausgabe :False True False
.b = a[:]
Kopierteil der Slice-Operator-Liste verloren, daher habe ich Ihre Antwort bearbeitet, um dort einen Kommentar zu erhalten. Es sieht so aus, als hätte ich gerade den Schwellenwert erreicht, um meine Änderungen nicht überprüfen zu müssen, bevor sie angewendet werden. Hoffentlich ist das cool für Sie. Unabhängig davon, hier ist eine nützliche Referenz zum Kopieren von Listen, auf die ich gestoßen==
. So ist5.0
beispielsweise ein Gleitkommawert, während5
es sich um eine Ganzzahl handelt. Aber5.0 == 5
immer noch zurückkehren ,True
weil sie den gleichen Wert darstellen. In Bezug auf Leistung undis
Ententypisierung wird der Interpreter immer durch Vergleichen der Speicheradressen des Operanden getestet, während==
es dem Objekt überlassen bleibt, zu entscheiden, ob es sich selbst als gleichwertig mit etwas anderem definiert.1000 is 10**3
wird in Python 3.7 als True ausgewertet, da 10 ** 3 vom Typ istint
.1000 is 1e3
Wird aber als falsch ausgewertet, da 1e3 vom Typ istfloat
.1000 is 10**3
zutrifft oder nicht , hängt von der Implementierung ab und hängt davon ab, ob der Compiler den Ausdruck vorab auswertet10**3
.x=10; 1000 is x**3
bewertet zuFalse
.Es gibt eine einfache Faustregel, die Ihnen sagt, wann Sie
==
oder verwenden sollenis
.==
ist für Wertgleichheit . Verwenden Sie diese Option, wenn Sie wissen möchten, ob zwei Objekte denselben Wert haben.is
ist als Referenzgleichheit . Verwenden Sie diese Option, wenn Sie wissen möchten, ob sich zwei Referenzen auf dasselbe Objekt beziehen.Im Allgemeinen, wenn Sie etwas auf eine einfache Art vergleichen, werden Sie in der Regel der Überprüfung für Wertgleichheit , so sollten Sie verwenden
==
. In Ihrem Beispiel soll beispielsweise geprüft werden, ob x einen Wert von 2 (==
) hat und nicht, obx
es sich buchstäblich auf dasselbe Objekt wie 2 bezieht.Noch etwas zu beachten: Aufgrund der Funktionsweise der CPython-Referenzimplementierung erhalten Sie unerwartete und inkonsistente Ergebnisse, wenn Sie fälschlicherweise die
is
Vergleichsgleichheit für Ganzzahlen verwenden:Das ist ziemlich genau das, was wir erwartet haben:
a
undb
haben den gleichen Wert, sind aber unterschiedliche Einheiten. Aber was ist damit?Dies stimmt nicht mit dem früheren Ergebnis überein. Was ist denn hier los? Es stellt sich heraus, dass die Referenzimplementierung von Python-Cache-Integer-Objekten im Bereich -5..256 aus Leistungsgründen als Singleton-Instanzen zwischengespeichert wird. Hier ist ein Beispiel, das dies demonstriert:
Dies ist ein weiterer offensichtlicher Grund, den Sie nicht verwenden sollten
is
: Das Verhalten bleibt den Implementierungen überlassen, wenn Sie es fälschlicherweise für die Wertgleichheit verwenden.quelle
a=500
undb=500
wollte ich nur darauf hinweisen, dass, wenn Siea
undb
auf einen Interger zwischen [-5, 256] setzen,a is b
tatsächlich zurückkehrtTrue
. Weitere Informationen hier: stackoverflow.com/q/306313/7571052==
bestimmt, ob die Werte gleich sind, währendis
bestimmt, ob sie genau dasselbe Objekt sind.quelle
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 :is
: Identitätsprüfung - Die Semantik lautet, dass das Objekt (wie im Speicher gespeichert) das Objekt ist. Wieder heißt es in der Dokumentation :Somit ist die Überprüfung auf Identität dieselbe wie die Überprüfung auf die Gleichheit der IDs der Objekte. Das ist,
ist das gleiche wie:
Wo
id
ist die eingebaute Funktion, die eine Ganzzahl zurückgibt, die "garantiert unter gleichzeitig vorhandenen Objekten eindeutig ist" (siehehelp(id)
) und woa
undb
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
Übliche Anwendungsfälle für
==
: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 einPEP 8 Richtungen
PEP 8, der offizielle Python-Styleguide für die Standardbibliothek, erwähnt außerdem zwei Anwendungsfälle für
is
: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,und im Interesse der Konsistenz empfiehlt:
Wir können sehen, dass dies das Standardverhalten für benutzerdefinierte Objekte ist:
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: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
: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.
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.quelle
is None
ist eine Ausnahme, aber das Gesagte== None
funktioniert auch ...is
zum Vergleichen vonEnum
s zu empfehlen .Was ist der Unterschied zwischen
is
und==
?==
undis
sind andere Vergleich! Wie andere bereits sagten:==
vergleicht die Werte der Objekte.is
vergleicht die Referenzen der Objekte.In Python beziehen sich Namen beispielsweise in diesem Fall auf Objekte
value1
undvalue2
auf eineint
Instanz, in der der Wert gespeichert ist1000
:Weil
value2
bezieht sich auf das gleiche Objektis
und==
wird gebenTrue
:Im folgenden Beispiel beziehen sich die Namen
value1
undvalue2
Verweise auf verschiedeneint
Instanzen, auch wenn beide dieselbe Ganzzahl speichern:Da der gleiche Wert (Ganzzahl) gespeichert
==
wird,True
wird er häufig als "Wertevergleich" bezeichnet. Allerdingsis
wird zurückkehren ,False
da diese unterschiedliche Objekte sind:Wann welche verwenden?
Im Allgemeinen
is
ist ein viel schnellerer Vergleich. Das ist der Grund, warum CPython bestimmte Objekte wie kleine Ganzzahlen, einige Zeichenfolgen usw. zwischenspeichert (oder vielleicht wiederverwendet ). Dies sollte jedoch als behandelt werden Implementierungsdetail werden , das sich (auch wenn es unwahrscheinlich ist) jederzeit ohne Vorwarnung ändern kann.Sie sollten nur verwenden,
is
wenn Sie:Ich möchte einen Wert mit einer Python- Konstante vergleichen . Die Konstanten in Python sind:
None
True
1False
1NotImplemented
Ellipsis
__debug__
int is int
oderint is float
)np.ma.masked
aus dem NumPy-Modul)In jedem anderen Fall sollten Sie verwenden
==
Gleichheit überprüfen.Kann ich das Verhalten anpassen?
Es gibt einen Aspekt, der
==
in den anderen Antworten noch nicht erwähnt wurde: Er ist Teil von Pythons "Datenmodell" . Das heißt, sein Verhalten kann mit der__eq__
Methode angepasst werden . Zum Beispiel:Dies ist nur ein künstliches Beispiel, um zu veranschaulichen, dass die Methode wirklich heißt:
Beachten Sie, dass standardmäßig (wenn keine andere Implementierung von
__eq__
in der Klasse oder den Oberklassen gefunden werden kann) Folgendes__eq__
verwendet wirdis
:Es ist also eigentlich wichtig zu implementieren
__eq__
wenn Sie "mehr" als nur einen Referenzvergleich für benutzerdefinierte Klassen wünschen!Auf der anderen Seite können Sie
is
Schecks nicht anpassen . Es wird immer nur vergleichen wenn Sie die gleiche Referenz haben.Werden diese Vergleiche immer einen Booleschen Wert zurückgeben?
Da
__eq__
es erneut implementiert oder überschrieben werden kann, ist es nicht auf returnTrue
oder beschränktFalse
. Es könnte alles zurückgeben (aber in den meisten Fällen sollte es einen Booleschen Wert zurückgeben!).Beispiel: Bei NumPy-Arrays
==
wird ein Array zurückgegeben:Aber
is
Schecks werden immer zurückkehrenTrue
oderFalse
!1 Wie Aaron Hall in den Kommentaren erwähnte:
Im Allgemeinen sollten Sie keine
is True
oderis False
Überprüfungen durchführen, da diese "Überprüfungen" normalerweise in einem Kontext verwendet werden, der die Bedingung implizit in einen Booleschen Wert konvertiert (z. B. in einerif
Anweisung). Also denis True
Vergleich machen und die implizite boolesche Besetzung machen also mehr Arbeit als nur die boolesche Besetzung - und Sie beschränken sich auf Boolesche Werte (was nicht als pythonisch angesehen wird).Wie PEP8 erwähnt:
quelle
is
- Namen, die auf Boolesche Werte verweisen, sollten mit einem booleschen Kontext überprüft werden - wieif __debug__:
oderif not __debug__:
. Sie sollten dies niemals tunif __debug__ is True:
oderif __debug__ == True:
- außerdem ist eine Konstante lediglich ein konstanter semantischer Wert, kein Singleton. Daher ist die Überprüfung mitis
in diesem Fall nicht semantisch korrekt. Ich fordere Sie auf, eine Quelle zu finden, die Ihre Behauptungen stützt - ich glaube nicht, dass Sie eine finden werden.None
,True
,False
und__debug__
sind , was Sie nennen würde „constant semantischen Wert“, weil sie nicht neu zugeordnet werden können. Aber alle sind Singletons.is True
oderif False
überprüfen wirklich (aber ja, diese sind ziemlich selten - aber wenn Sie sie tun, können Sie sie mit verwendenis
). Deshalb benutzt sie manchmal sogar CPython (zum Beispiel hier oder hier )Sie sind völlig anders .
is
prüft auf Objektidentität,==
prüft auf Gleichheit (ein Begriff, der von den Typen der beiden Operanden abhängt).Es ist nur ein glücklicher Zufall, dass "
is
" mit kleinen ganzen Zahlen (z. B. 5 == 4 + 1) richtig zu funktionieren scheint. Dies liegt daran, dass CPython die Speicherung von Ganzzahlen im Bereich (-5 bis 256) optimiert, indem sie zu Singletons gemacht werden . Dieses Verhalten ist vollständig implementierungsabhängig und kann nicht garantiert werden, wenn kleinere transformative Operationen ausgeführt werden.In Python 3.5 werden beispielsweise auch Singletons für kurze Zeichenfolgen erstellt, deren Aufteilung jedoch dieses Verhalten stört:
quelle
https://docs.python.org/library/stdtypes.html#comparisons
is
Identitätsprüfungen==
auf GleichheitJeder (kleine) ganzzahlige Wert wird einem einzelnen Wert zugeordnet, sodass alle 3 identisch und gleich sind. Dies ist ein Implementierungsdetail, das jedoch nicht Teil der Sprachspezifikation ist
quelle
Ihre Antwort ist richtig. Der
is
Operator vergleicht die Identität zweier Objekte. Das==
Operator vergleicht die Werte zweier Objekte.Die Identität eines Objekts ändert sich nach seiner Erstellung nie mehr. Sie können es sich als die Adresse des Objekts im Speicher vorstellen.
Sie können das Vergleichsverhalten von Objektwerten steuern, indem Sie eine
__cmp__
Methode oder eine umfangreiche Vergleichsmethode wie definieren__eq__
.quelle
Schauen Sie sich die Frage zum Stapelüberlauf an. Pythons Operator "is" verhält sich unerwartet mit ganzen Zahlen .
Worauf es hauptsächlich ankommt, ist, dass "
is
" prüft, ob es sich um dasselbe Objekt handelt, nicht nur um dasselbe (die Zahlen unter 256 sind ein Sonderfall).quelle
Auf den Punkt gebracht wird
is
geprüft, ob zwei Referenzen auf dasselbe Objekt verweisen oder nicht.==
prüft, ob zwei Objekte den gleichen Wert haben oder nicht.quelle
Wie John Feminella sagte, werden Sie meistens == und! = Verwenden, weil Ihr Ziel darin besteht, Werte zu vergleichen. Ich möchte nur kategorisieren, was Sie den Rest der Zeit tun würden:
Es gibt nur eine Instanz von NoneType, dh None ist ein Singleton. Folglich
foo == None
undfoo is None
bedeuten das gleiche. Deris
Test ist jedoch schneller und es ist die Pythonic-Konvention zu verwendenfoo is None
.Wenn Sie eine Selbstbeobachtung durchführen oder sich mit der Speicherbereinigung beschäftigen oder prüfen, ob Ihr benutzerdefiniertes String-Internierungs-Gadget funktioniert oder ähnliches, dann haben Sie wahrscheinlich einen Anwendungsfall für
foo
isbar
.Richtig und Falsch sind (jetzt) auch Singletons, aber es gibt keinen Anwendungsfall für
foo == True
und keinen Anwendungsfall fürfoo is True
.quelle
Die meisten von ihnen haben bereits auf den Punkt geantwortet. Nur als zusätzliche Anmerkung (basierend auf meinem Verständnis und Experimentieren, aber nicht aus einer dokumentierten Quelle), die Aussage
von oben Antworten sollten als gelesen werden
. Ich bin zu diesem Schluss gekommen, basierend auf dem folgenden Test:
Hier sind der Inhalt der Liste und des Tupels gleich, aber der Typ / die Klasse sind unterschiedlich.
quelle
Python Unterschied zwischen ist und gleich (==)
Hier ist ein Beispiel, um die Ähnlichkeit und den Unterschied zu demonstrieren.
quelle
Da die anderen Personen in diesem Beitrag die Frage ausführlich beantworten, möchte ich hauptsächlich den Vergleich zwischen und für Zeichenfolgen hervorheben
is
==
, die zu unterschiedlichen Ergebnissen führen können, und die Programmierer auffordern, diese sorgfältig zu verwenden.Bei String - Vergleich, stellen Sie sicher zu verwenden ,
==
stattis
:Aus:
Aber im folgende Beispiel
==
undis
unterschiedliche Ergebnisse erhalten:Aus:
Fazit:
Verwenden Sie
is
sorgfältig zwischen Strings vergleichenquelle