Warum führt der Vergleich von Strings mit ‘==’ oder ‘is’ manchmal zu unterschiedlichen Ergebnissen?

Lesezeit: 7 Minuten

Benutzer-Avatar
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.

    – 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

Benutzer-Avatar
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


Benutzer-Avatar
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!

    – Sнаđошƒаӽ

    19. Juli 2015 um 5:46 Uhr

  • @NoctisSkytower hat dasselbe gegoogelt und dies gefunden guilload.com/python-string-interning

    – Xtreak

    10. März 2016 um 14:41 Uhr

  • @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.

Benutzer-Avatar
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.

Benutzer-Avatar
Gregor Lind

Dies ist eine Randnotiz, aber in idiomatischem Python werden Sie oft Dinge sehen wie:

if x is None:
    # Some clauses

Das ist sicher, weil es gibt garantiert eine Instanz des Null-Objekts (dh None).

  • 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

Benutzer-Avatar
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.

Hier ist ein gutes Beispiel:

>>> s1 = u'public'
>>> s2 = 'public'
>>> s1 is s2
False
>>> s1 == s2
True

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

1153410cookie-checkWarum führt der Vergleich von Strings mit ‘==’ oder ‘is’ manchmal zu unterschiedlichen Ergebnissen?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy