Frage Warum erzeugt das Vergleichen von Strings in Python mit '==' oder 'is' manchmal ein anderes Ergebnis?


Ich habe ein Python-Programm, bei dem zwei Variablen auf den Wert gesetzt sind 'public'. In einem bedingten Ausdruck habe ich den Vergleich var1 is var2 was scheitert, aber wenn ich es zu ändern var1 == var2 es kehrt zurück True.

Wenn ich nun meinen Python-Interpreter öffne und den gleichen "Ist" -Vergleich mache, ist es erfolgreich.

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

Was fehlt mir hier?


891
2017-10-01 15:40


Ursprung


Antworten:


is ist Identitätsprüfung, == ist Gleichheitsprüfung. Was in Ihrem Code passiert, würde im Interpreter folgendermaßen emuliert:

>>> a = 'pub'
>>> b = ''.join(['p', 'u', 'b'])
>>> a == b
True
>>> a is b
False

Also, kein Wunder, dass sie nicht gleich sind, oder?

Mit anderen Worten: is ist der id(a) == id(b)


1230
2017-10-01 15:45



Andere Antworten hier sind richtig: is wird für verwendet Identität Vergleich, während == wird für verwendet Gleichberechtigung Vergleich. Da ist was Gleichheit (die zwei Zeichenketten sollten die gleichen Buchstaben enthalten), in diesem Fall die is Betreiber ist einfach falsch und Sie sollten verwenden == stattdessen.

Der Grund is interaktiv arbeitet, sind (meist) String-Literale interniert standardmäßig. Aus Wikipedia:

Internierte Strings beschleunigen die Zeichenfolge   Vergleiche, die manchmal a   Performance-Engpass in Anwendungen   (wie Compiler und dynamische   Programmiersprachen Laufzeiten)   verlassen sich stark auf Hash-Tabellen mit   String-Schlüssel. Ohne zu internieren,   Überprüfen, dass zwei verschiedene Zeichenfolgen   sind gleichbedeutend mit jeder Prüfung   Zeichen beider Zeichenfolgen. Das ist   langsam aus mehreren Gründen: Es ist   inhärent O (n) in der Länge der   Saiten; es erfordert normalerweise Lesevorgänge   aus mehreren Speicherbereichen, die   nimm dir Zeit; und die Lesevorgänge füllen die   Prozessor-Cache, dh es gibt weniger   Cache für andere Bedürfnisse verfügbar. Mit   internierte Strings, ein einfaches Objekt   Identitätstest genügt nach dem   ursprünglicher interner Betrieb; das ist   typischerweise als Zeiger implementiert   Gleichheitstest, normalerweise nur ein einziger   Maschinenbefehl ohne Speicher   Referenz überhaupt.

Also, wenn Sie zwei String-Literale (Wörter, die buchstäblich in Ihren Programmquellcode eingetippt sind, umgeben von Anführungszeichen) in Ihrem Programm, die den gleichen Wert haben, interniert der Python-Compiler automatisch die Strings, so dass sie beide gleichzeitig gespeichert werden Speicherort. (Beachten Sie, dass dies nicht der Fall ist immer passieren, und die Regeln dafür, wann dies passiert, sind ziemlich verworren, also bitte verlasse dich nicht auf dieses Verhalten im Produktionscode!)

Da in Ihrer interaktiven Sitzung beide Zeichenketten tatsächlich am selben Speicherort gespeichert sind, haben sie dasselbe Identitätso is Operator funktioniert wie erwartet. Aber wenn Sie eine Zeichenfolge mit einer anderen Methode erstellen (auch wenn diese Zeichenfolge enthält) genau die gleichen Zeichen), dann kann die Zeichenfolge sein gleich, aber es ist nicht die gleiche Zeichenfolge - Das ist anders Identität, weil es an einem anderen Ort im Speicher gespeichert ist.


440
2017-10-01 16:02



Das isSchlüsselwort ist ein Test für die Objektidentität während == ist ein Wertvergleich.

Wenn du benutzt is, das Ergebnis ist genau dann wahr, wenn das Objekt das gleiche Objekt ist. Jedoch, == wird immer dann wahr sein, wenn die Werte des Objekts gleich sind.


94
2017-10-01 15:45



Eine letzte Sache zu beachten, können Sie die interne Funktion verwenden, um sicherzustellen, dass Sie einen Verweis auf die gleiche Zeichenfolge erhalten:

>>> a = intern('a')
>>> a2 = intern('a')
>>> a is a2
True

Wie oben erwähnt, sollten Sie wahrscheinlich nicht die Gleichheit von Strings bestimmen. Aber das kann hilfreich sein zu wissen, ob Sie eine seltsame Anforderung haben is.

Beachten Sie, dass die interne Funktion von einer eingebauten Funktion in das Modul verschoben wurde sys für Python 3.


48
2017-10-01 16:04



is ist Identitätsprüfung, == ist Gleichheitsprüfung. Was das bedeutet ist das is ist eine Möglichkeit zu überprüfen, ob zwei Dinge sind gleich Dinge oder nur gleichwertig.

Sag, du hast ein einfaches person Objekt. Wenn es "Jack" genannt wird und "23" Jahre alt ist, entspricht es einem anderen 23-jährigen Jack, aber es ist nicht die gleiche 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 gleich alt, aber sie sind nicht die gleiche Person. Eine Zeichenfolge könnte einer anderen entsprechen, aber es ist nicht das gleiche Objekt.


28
2018-04-29 00:56



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

if x is None: 
    # some clauses

Das ist sicher, weil es gibt garantiert eine Instanz des Null-Objekts (d. h. keine).


27
2017-10-01 18:51



Wenn Sie nicht sicher sind, was Sie tun, verwenden Sie die '=='. Wenn Sie ein wenig mehr darüber wissen, können Sie 'Ist' für bekannte Objekte wie 'Keine' verwenden.

Sonst wirst du dich wundern, warum die Dinge nicht funktionieren 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 gleich bleiben.


23
2017-10-01 16:57



Aus meiner begrenzten Erfahrung mit Python, is wird verwendet, um zwei Objekte zu vergleichen, um zu sehen, ob sie das gleiche 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 Zeichenfolge. Sie sind nicht vom selben Typ, aber sie haben denselben Wert.


16
2017-10-01 15:48