Warum führt der Vergleich von Strings mit ‘==’ oder ‘is’ manchmal zu unterschiedlichen Ergebnissen?
Lesezeit: 7 Minuten
jottos
Zwei String-Variablen werden auf denselben Wert gesetzt. s1 == s2 kehrt immer zurück Trueaber s1 is s2 kehrt manchmal zurück False.
Wenn ich meinen Python-Interpreter öffne und dasselbe mache is Vergleich, es gelingt:
>>> s1 = 'text'
>>> s2 = 'text'
>>> s1 is s2
True
Warum ist das?
siehe: stackoverflow.com/questions/1392433/…
– Nick Dandoulakis
1. Oktober 2009 um 15:50 Uhr
Dieses Problem tritt auch auf, wenn Sie eine Konsoleneingabe lesen, z. input = raw_input("Decide (y/n): "). In diesem Fall eine Eingabe von “y” und if input == 'y':wird “True” zurückgeben, während if input is 'y': wird False zurückgeben.
Wie @chris-rico erwähnt, habe ich hier eine großartige Erklärung: stackoverflow.com/q/15541404/1695680
– ThorSummoner
6. Oktober 2016 um 15:43 Uhr
Mögliches Duplikat von Gibt es einen Unterschied zwischen `==` und `is` in Python?
– Taknok
14. August 2017 um 19:24 Uhr
SilentGhost
is ist Identitätsprüfung, == ist ein Gleichheitstest. Was in Ihrem Code passiert, würde im Interpreter wie folgt emuliert:
>>> a="pub"
>>> b = ''.join(['p', 'u', 'b'])
>>> a == b
True
>>> a is b
False
Kein Wunder also, dass sie nicht gleich sind, oder?
Mit anderen Worten: a is b ist das Äquivalent von id(a) == id(b)
ahh dasselbe wie eq? gegen gleich? im Schema, verstanden.
– Jottos
1. Oktober 2009 um 17:00 Uhr
Oder == vs .equals() auf Java. Das Beste daran ist, dass die Python == ist nicht analog zu Java ==.
– Tyler
4. Februar 2012 um 2:48 Uhr
@Крайст: Es gibt nur eine einzige None Wert. Es hat also immer die gleiche ID.
– SilentGhost
29. Oktober 2012 um 9:57 Uhr
Dies geht nicht auf das Beispiel “ist -> True” des OP ein.
– Benutzer2864740
10. September 2014 um 4:53 Uhr
@AlexanderSupertramp, wegen String-Interning.
– Chris Rico
1. Februar 2015 um 9:34 Uhr
Daniel Priden
Andere Antworten hier sind richtig: is wird verwendet für Identität Vergleich, während == wird verwendet für Gleichberechtigung Vergleich. Da es Ihnen um Gleichheit geht (die beiden Zeichenfolgen sollten dieselben Zeichen enthalten), ist in diesem Fall die is Operator ist einfach falsch und Sie sollten verwenden == stattdessen.
Der Grund is interaktiv funktioniert ist, dass (die meisten) String-Literale sind interniert standardmäßig. Aus Wikipedia:
Internierte Zeichenfolgen beschleunigen Zeichenfolgenvergleiche, die manchmal einen Leistungsengpass in Anwendungen darstellen (z. B. Compiler und Laufzeitumgebungen für dynamische Programmiersprachen), die stark auf Hash-Tabellen mit Zeichenfolgenschlüsseln angewiesen sind. Ohne zu internieren, beinhaltet die Überprüfung, ob zwei verschiedene Zeichenfolgen gleich sind, die Untersuchung jedes Zeichens beider Zeichenfolgen. Dies ist aus mehreren Gründen langsam: Es ist von Natur aus O(n) in der Länge der Zeichenfolgen; Es erfordert normalerweise Lesevorgänge aus mehreren Speicherbereichen, die einige Zeit in Anspruch nehmen. und die Lesevorgänge füllen den Prozessor-Cache auf, was bedeutet, dass weniger Cache für andere Anforderungen verfügbar ist. Bei internierten Strings genügt ein einfacher Objektidentitätstest nach der ursprünglichen internen Operation; Dies wird typischerweise als Zeigergleichheitstest implementiert, normalerweise nur ein einzelner Maschinenbefehl ohne jegliche Speicherreferenz.
Wenn Sie also zwei Zeichenfolgenliterale (Wörter, die buchstäblich in Ihren Programmquellcode eingegeben und von Anführungszeichen umgeben sind) in Ihrem Programm haben, die denselben Wert haben, interniert der Python-Compiler automatisch die Zeichenfolgen, sodass sie beide gleichzeitig gespeichert werden Speicherort. (Beachten Sie, dass dies nicht der Fall ist stets passieren, und die Regeln dafür sind ziemlich kompliziert, also verlassen Sie sich bitte nicht auf dieses Verhalten im Produktionscode!)
Da in Ihrer interaktiven Sitzung beide Zeichenfolgen tatsächlich an derselben Speicherstelle gespeichert sind, haben sie dasselbe Identitätalso die is Betreiber funktioniert wie erwartet. Aber wenn Sie eine Zeichenfolge mit einer anderen Methode erstellen (selbst wenn diese Zeichenfolge enthält exakt die gleichen Zeichen), dann kann die Zeichenfolge sein gleichaber es ist nicht dieselbe Saite – das heißt, es hat eine andere Identitätweil es an einer anderen Stelle im Speicher gespeichert ist.
Wo kann jemand mehr über die komplizierten Regeln für das Internieren von Zeichenfolgen lesen?
– Noctis-Skytower
11. April 2013 um 14:14 Uhr
+1 für eine gründliche Erklärung. Ich bin mir nicht sicher, wie die andere Antwort so viele positive Stimmen erhalten hat, ohne zu erklären, was TATSÄCHLICH passiert ist.
– Dieser Typ
29. April 2013 um 2:07 Uhr
genau das ist mir auch in den Sinn gekommen, als ich die Frage gelesen habe. Die akzeptierte Antwort ist kurz, enthält jedoch die Tatsache, aber diese Antwort erklärt Dinge viel besser. Nett!
@naught101: Nein, die Regel ist, zwischen zu wählen == und is je nachdem, welche Art von Überprüfung Sie möchten. Wenn Sie sich um die Saiten kümmern gleich (d. h. mit gleichem Inhalt) sollten Sie immer verwenden ==. Wenn es Ihnen wichtig ist, ob sich zwei beliebige Python-Namen auf dieselbe Objektinstanz beziehen, sollten Sie verwenden is. Du brauchst vielleicht is wenn Sie Code schreiben, der viele verschiedene Werte verarbeitet, ohne sich um deren Inhalt zu kümmern, oder wenn Sie wissen, dass es nur einen von etwas gibt und Sie andere Objekte ignorieren möchten, die vorgeben, dieses Ding zu sein. Wenn Sie sich nicht sicher sind, wählen Sie immer ==.
– Daniel Priden
18. Oktober 2016 um 19:30 Uhr
Das is Schlüsselwort ist ein Test für die Objektidentität while == ist ein Wertevergleich.
Wenn du benutzt is, ist das Ergebnis genau dann wahr, wenn das Objekt dasselbe Objekt ist. Jedoch, == ist immer dann wahr, wenn die Werte des Objekts gleich sind.
TankorSmash
is ist Identitätsprüfung und == ist ein Gleichheitstest. Das heisst is ist eine Möglichkeit zu überprüfen, ob zwei Dinge die sind gleich Dinge, oder einfach nur gleichwertig.
Angenommen, Sie haben eine einfache person Objekt. Wenn es „Jack“ heißt und „23“ Jahre alt ist, entspricht es einem anderen 23-jährigen Jack, aber es ist nicht dieselbe Person.
class Person(object):
def __init__(self, name, age):
self.name = name
self.age = age
def __eq__(self, other):
return self.name == other.name and self.age == other.age
jack1 = Person('Jack', 23)
jack2 = Person('Jack', 23)
jack1 == jack2 # True
jack1 is jack2 # False
Sie sind im gleichen Alter, aber sie sind nicht die gleiche Person. Ein String kann einem anderen äquivalent sein, aber es ist nicht dasselbe Objekt.
Gregor Lind
Dies ist eine Randnotiz, aber in idiomatischem Python werden Sie oft Dinge sehen wie:
Gilt das auch für True und False? Nur eine Instanz wird also übereinstimmen?
– HandyManDan
1. Juni 2018 um 18:00 Uhr
@HandyManDan Ja, sie sind sowohl in Python 2 als auch in Python 3 Singletons.
– kamillitw
16. November 2018 um 9:40 Uhr
@kamillitw, aber in Python 2 können Sie False und True neu zuweisen.
– Martijn Pieters ♦
10. März 2019 um 1:29 Uhr
Matthias Nilson
Wenn Sie sich nicht sicher sind, was Sie tun, verwenden Sie das ‘==’. Wenn Sie etwas mehr Wissen darüber haben, können Sie ‘is’ für bekannte Objekte wie ‘None’ verwenden.
Sonst fragt man sich am Ende, warum es nicht funktioniert und warum das passiert:
>>> a = 1
>>> b = 1
>>> b is a
True
>>> a = 6000
>>> b = 6000
>>> b is a
False
Ich bin mir nicht einmal sicher, ob einige Dinge zwischen verschiedenen Python-Versionen/Implementierungen garantiert gleich bleiben.
Gilt das auch für True und False? Nur eine Instanz wird also übereinstimmen?
– HandyManDan
1. Juni 2018 um 18:00 Uhr
@HandyManDan Ja, sie sind sowohl in Python 2 als auch in Python 3 Singletons.
– kamillitw
16. November 2018 um 9:40 Uhr
@kamillitw, aber in Python 2 können Sie False und True neu zuweisen.
– Martijn Pieters ♦
10. März 2019 um 1:29 Uhr
Aus meiner begrenzten Erfahrung mit Python, is wird verwendet, um zwei Objekte zu vergleichen, um zu sehen, ob sie dasselbe Objekt sind, im Gegensatz zu zwei verschiedenen Objekten mit demselben Wert. == wird verwendet, um festzustellen, ob die Werte identisch sind.
s1 ist eine Unicode-Zeichenfolge, und s2 ist eine normale Saite. Sie sind nicht vom gleichen Typ, haben aber den gleichen Wert.
Dieses Ergebnis hat einen anderen Grund: Vergleichen einer Unicode-Zeichenfolge (<type 'unicode'>) in eine Nicht-Unicode-Zeichenfolge (<type 'str'>). Es ist ein Verhalten, das für Python 2 spezifisch ist. In Python 3, beides s1 und vom Typ sind strund beide is und == Rückkehr True.
– 0 _
17. April 2021 um 11:38 Uhr
11534100cookie-checkWarum führt der Vergleich von Strings mit ‘==’ oder ‘is’ manchmal zu unterschiedlichen Ergebnissen?yes
siehe: stackoverflow.com/questions/1392433/…
– Nick Dandoulakis
1. Oktober 2009 um 15:50 Uhr
Dieses Problem tritt auch auf, wenn Sie eine Konsoleneingabe lesen, z.
input = raw_input("Decide (y/n): ")
. In diesem Fall eine Eingabe von “y” undif input == 'y':
wird “True” zurückgeben, währendif input is 'y':
wird False zurückgeben.– Semjon Mössinger
21. August 2016 um 11:09 Uhr
Dieser Blog bietet eine weitaus vollständigere Erklärung als jede Antwort guilload.com/python-string-interning
– Chris_Rands
5. Oktober 2016 um 8:04 Uhr
Wie @chris-rico erwähnt, habe ich hier eine großartige Erklärung: stackoverflow.com/q/15541404/1695680
– ThorSummoner
6. Oktober 2016 um 15:43 Uhr
Mögliches Duplikat von Gibt es einen Unterschied zwischen `==` und `is` in Python?
– Taknok
14. August 2017 um 19:24 Uhr