1322 Stimmen

Warum führt der Vergleich von Zeichenketten mit "==" oder "ist" manchmal zu einem anderen Ergebnis?

Zwei String-Variablen werden auf denselben Wert gesetzt. s1 == s2 gibt immer zurück True aber s1 is s2 kehrt manchmal zurück False .

Wenn ich meinen Python-Interpreter öffne und das Gleiche tue is Vergleich gelingt es:

>>> s1 = 'text'
>>> s2 = 'text'
>>> s1 is s2
True

Warum ist das so?

1683voto

SilentGhost Punkte 285785

is ist die Identitätsprüfung, == ist die Gleichheitsprüfung. Was in Ihrem Code passiert, wird im Interpreter so nachgebildet:

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

Kein Wunder also, dass sie nicht dasselbe sind, oder?

Mit anderen Worten: a is b ist das Äquivalent zu id(a) == id(b)

663voto

Daniel Pryden Punkte 56882

Die anderen Antworten sind richtig: is wird verwendet für Identität Vergleich, während == wird verwendet für Gleichstellung Vergleich. Da es Ihnen um die Gleichheit geht (die beiden Zeichenketten sollten die gleichen Zeichen enthalten), wird in diesem Fall die is Operator ist einfach falsch, und Sie sollten den == stattdessen.

Der Grund is interaktiv funktioniert, ist, dass (die meisten) String-Literale interniert standardmäßig. Aus Wikipedia:

Internierte Zeichenketten beschleunigen String Vergleiche, die manchmal einen Leistungsengpass in Anwendungen (wie Compilern und dynamischen Programmiersprachen-Laufzeiten), die stark auf Hash-Tabellen mit String-Schlüsseln String-Schlüsseln. Ohne Internierung, die Überprüfung, ob zwei verschiedene Zeichenketten gleich sind, muss jeder Zeichen beider Zeichenketten. Dies ist aus mehreren Gründen langsam: Es ist von Natur aus O(n) für die Länge der Zeichenketten; es erfordert typischerweise Lesevorgänge aus mehreren Speicherregionen, was Zeit Zeit in Anspruch nehmen; und das Lesen füllt den Prozessor-Cache, was bedeutet, dass weniger Cache für andere Zwecke zur Verfügung steht. Mit internierten Strings reicht ein einfacher Objekt Identitätstest aus, nachdem die ursprünglichen internen Operation; dies wird typischerweise als Zeiger Gleichheitstest implementiert, normalerweise nur ein einziger Maschinenbefehl ohne Speicher Referenz überhaupt.

Wenn Sie also zwei String-Literale (Wörter, die buchstäblich in den Quellcode Ihres Programms eingegeben werden, umgeben von Anführungszeichen) in Ihrem Programm haben, die denselben Wert haben, interniert der Python-Compiler die Strings automatisch, so dass sie beide an derselben Speicherstelle gespeichert werden. (Beachten Sie, dass dies nicht toujours passieren, und die Regeln, wann dies geschieht, sind ziemlich verworren, also verlassen Sie sich bitte nicht auf dieses Verhalten im Produktionscode).

Da in Ihrer interaktiven Sitzung beide Zeichenketten am gleichen Speicherort gespeichert sind, haben sie den gleichen Identität , so dass die is Operator funktioniert wie erwartet. Wenn Sie jedoch eine Zeichenkette mit einer anderen Methode konstruieren (auch wenn diese Zeichenkette genau die gleichen Zeichen), dann kann die Zeichenfolge gleich aber es ist nicht die gleiche Zeichenkette -- das heißt, sie hat eine andere Identität weil sie an einer anderen Stelle im Speicher abgelegt ist.

123voto

Thomas Owens Punkte 110966

El is Schlüsselwort ist ein Test für die Objektidentität, während == ist ein Wertevergleich.

Wenn Sie is ist das Ergebnis nur dann wahr, wenn es sich bei dem Objekt um dasselbe Objekt handelt. Allerdings, == ist immer dann wahr, wenn die Werte des Objekts identisch sind.

67voto

Jason Baker Punkte 180981

Ein letzter Hinweis: Sie können die sys.intern Funktion, um sicherzustellen, dass Sie einen Verweis auf dieselbe Zeichenfolge erhalten:

>>> from sys import intern
>>> a = intern('a')
>>> a2 = intern('a')
>>> a is a2
True

Wie bereits erwähnt, sollten Sie nicht mit is um die Gleichheit von Zeichenketten festzustellen. Aber es kann hilfreich sein, dies zu wissen, wenn Sie irgendeine Art von seltsamer Anforderung haben, zu verwenden is .

Beachten Sie, dass die intern Funktion war in Python 2 ein builtin, wurde aber in die sys Modul in Python 3.

49voto

TankorSmash Punkte 11579

is ist die Identitätsprüfung und == ist die Gleichheitsprüfung. Dies bedeutet is ist eine Möglichkeit zu prüfen, ob zwei Dinge gleich sind dieselbe Dinge, oder einfach 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 gleich alt, aber sie sind nicht derselbe Typ Mensch. Eine Zeichenkette mag einer anderen gleichwertig sein, aber sie ist nicht dasselbe Objekt.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X