Sehr wichtige Operatoren, die du in Python kennen solltest, sind die sogenannten Identitätsoperatoren – is und is not.
Es ist, häufig unter Anfängern, nicht ganz einfach zu verstehen, was der Unterschied zwischen is und == („gleich“) ist. Ich möchte deshalb versuchen dir diesen Unterschied in diesem Artikel so einfach, wie möglich zu erklären und ein paar Beispiele dazu geben.
Die Identitäts-Funktion in Python
Bevor wir uns die Identitätsperatoren anschauen, möchte ich kurz auf die Identitäts-Funktion id() in Python eingehen.
Wenden wir diese auf ein Objekt an, bekommen wir eine natürliche Zahl zurückgegeben. Aber was bedeutet diese Zahl?
Schauen wir uns folgendes Beispiel an:
x = 2
print(id(x))
Nach Interpretieren des Codes erhalten wir auf der Console folgende Ausgabe.
140299411265872
Die Identitäts-Funktion gibt also für jedes Objekt in Python eine ganze Zahl aus. Diese bezieht sich auf den Speicherort des Objekts.
In unserem Beispiel haben wir also den Wert 2 genommen und der Variablen x zugewiesen. Irgendwo ist dieser Wert 2 nun gespeichert und die Variable x zeigt darauf, bzw. verweist darauf.
Python sucht sich einen Speicherort für die Werte, die im Verlauf deines Codes vorkommen, aus und gibt diesen eine Nummer.
Die Identitäts-Funktion gibt also Zahlen aus, die wir uns also als Adresse vorstellen können, die uns Aufschluss über den Speicherort des gespeicherten Objekts im Arbeitsspeicher gibt.
Wenn du zu einem anderen Zeitpunkt oder an einem anderen Computer den gleichen Code durchlaufen lässt, wirst du auch eine andere Zahl durch die Identitäts-Funktion erhalten. Der Speicherort bezieht sich nur auf deinen Computer, dein Programm und deine Einstellungen, die du in Python vorgenommen hasst.
Die Operatoren „is“ und „is not“ in Python
Jetzt zum eigentlichen Thema dieses Beitrags.
Zwischen zwei Objekten können die Operatoren „is“ und „is not“ stehen, die sogenannten Identitätsoperatoren in Python.
Was bewirken denn diese Identitätsoperatoren?
Zwei Objekte sind bezüglich des Operators „is“ als gleich anzusehen, wenn sie bezüglich der id()-Funktion, also der Identitäts-Funktion, den gleichen ganzzahligen Wert haben. Sprich, sie haben den gleichen Speicherort.
Anders ausgedrückt, die Aussage „a is b“ ist wahr oder True, falls a und b auf den gleichen Speicherort verweisen.
Wieder schauen wir uns ein Beispiel an, um das Ganze genauer zu verstehen.
x = "Hi"
y = x
print(id(x))
print(id(y))
print(x is y)
Schauen wir uns das Ergebnis des Codes auf der Console an.
140299476798448 140299476798448 True
Wir haben eine Variable x deklariert und dieser den Wert „Hi“ zugeordnet. Diese Variable x verweist nun also auf den Speicherort, wo der Wert „Hi“ zu finden ist, in deinem Computer.
Anschließend wurde eine weitere Variable y deklariert und dieser wurde x zugewiesen, also zeigt auch die Variable y auf den Speicherort, auf den auch x verweist.
Deshalb haben wir am Ende die gleiche Zahl bei beiden, wenn wir die Identitäts-Funktion id() auf x bzw. y anwenden.
Das Endergebnis ist, die Aussage „x is y“ ist True, also wahr.
Kommen wir zum nächsten Beispiel. Beide Variablen x und y bekommen den gleichen Wert zugewiesen, aber sie haben sonst nichts miteinander zu tun. Das heißt, bei der Deklaration (Erstellung) der Variablen x und y haben wir überhaupt keinen Bezug auf die jeweils andere Variable genommen.
Python wird also jeder Variablen einen eigenen Speicherort zuweisen und somit werden beide einen unterschiedlichen Wert ausgeben, wenn man sie in die id()-Funktion einsetzt.
Schauen wir uns an, was ich meine.
x = "Hallo!"
y = "Hallo!"
print(id(x))
print(id(y))
print(x is y)
Siehe da, auf der Console erscheint folgendes Ergebnis.
140299476843632 140299476843568 False
Tatsächlich, die beiden Variablen sind nicht gleich im Sinne von „is“, weil sie nicht auf den gleichen Speicherort verweisen, aber natürlich haben sie den gleichen Wert.
Unterschied zwischen „is“ und „==“ Operator in Python
Genau hier liegt der Unterschied zwischen dem Vergleichsoperator == und dem Identitätsoperator is.
Der erste vergleicht, ob zwei Objekte den gleichen Wert haben und der zweite Operator, is, vergleicht, ob zwei Objekte auf den gleichen Speicherort verweisen.
Ich hoffe, das folgende Beispiel kann dir helfen, das zu verstehen.
x = "Hallo..."
y = "Hallo..."
print(x == y)
print(x is y)
True False
Natürlich haben in diesem Beispiel die beiden Variablen x und y den gleichen Wert, nämlich die Zeichenkette „Hallo…“. Aber sie wurden völlig unabhängig voneinander deklariert und verweisen somit auf unterschiedliche Speicherorte.
Deshalb erhalten wir für den ersten Ausdruck True und den zweiten Ausdruck False.
Ist „!=“ und „is not“ das Gleiche?
Diese Frage beantwortet sich aus der Überlegung des vorherigen Abschnitts. Alle Objekte, denen nicht die gleichen Werte zugeordnet wurden, sind ungleich.
Ein Objekt A „is not“ Objekt B gilt, wenn die beiden Objekte nicht auf den gleichen Ort im Speicher verweisen.
Zudem sind zwei Objekte von verschiedenem Datentyp automatisch immer ungleich, also in Bezug auf ihren Wert (!=) und in Bezug auf ihren Speicherort, also ihrer Identität (is not).
Sieh dir dieses Beispiel an.
liste = [1, 2, 3]
string = "123"
print(liste != string)
print(liste is not string)
Das Ergebnis ist:
True True
Natürlich ist eine Liste vom Wert her nicht das Gleiche, wie eine Zeichenkette und somit ungleich !=.
Allerdings können diese beiden Objekte auch nicht auf den gleichen Speicherort verweisen und deshalb kommt als Ergebnis für den Ausdruck „liste is not string“ auch der Wert True heraus.
Ausnahme Caching: Der is-Operator verhält sich seltsam
Manchmal verhalten sich die Operatoren is und is not, also die Identitätsoperatoren in Python seltsam.
Eine wichtige Ausnahme gilt es zu beachten, nämlich die Identität von ganzen Zahlen, also integers und Zeichenketten, strings. Diese werden von Python (teilweise) gecacht.
is und is not Operator bei ganzen Zahlen
Wenn du Variablen deklarierst und diesen den Wert einer Zahl von -5 bis +256 zuweist, dann können auch verschiedene Variablen auf den gleichen Speicherort verweisen.
Salopp gesagt hat Python einfach grundsätzlich einen Array (Liste) mit den Zahlen von -5 bis +256 gespeichert, mit fixem Speicherort.
Wann immer du nun eine Variable deklarierst und ihr den Wert einer ganzen Zahl von -5 bis 256 zuweist, dann verweist die Variable einfach auch auf diesen schon festgesetzten Speicherort.
Disclaimer: Ich verwende aktuell Python 3.10.5 und ich habe in Python IDLE festgestellt, dass dies nicht nur für ganze Zahlen von -5 bis 256, sondern für alle ganzen Zahlen gilt. Abhängig von deiner Pythonversion können hier unterschiedliche Ergebnisse auftauchen.
Hört sich kompliziert an, ist es aber nicht.
Python denkt sich einfach, diese Zahlen zwischen -5 und +256 werden sowieso ganz häufig verwendet. Egal welcher Variablen so ein Wert zugewiesen wird, diese Variablen verweisen dann einfach immer auf denselben Speicherort. (Zumindest ist das die Erklärung, die ich hier gefunden habe – auf Englisch)
Schau dir ein Beispiel an, dann wird es klar.
x = 2
y = 2
print(x is y)
print("Speicherort von x:", id(x), "und Speicherort von y:", id(y))
u = 256
v = 256
print(u is v)
print("Speicherort von u:", id(u), "und Speicherort von v:", id(v))
a = 257
b = 257
print(a is b)
print("Speicherort von a:", id(a), "und Speicherort von b:", id(b))
Klicke auf „Run“ und du wirst folgende Ausgabe erhalten.
True Speicherort von x: 140299411265872 und Speicherort von y: 140299411265872 True Speicherort von u: 140299411462544 und Speicherort von v: 140299411462544 False Speicherort von a: 140299476833136 und Speicherort von b: 140299476833744
Nochmal der Disclaimer, bei anderen Editoren und neueren Pythonversionen kann es durchaus sein, dass auch ganze Zahlen größer als 257 bereits im Cache gespeichert sind und somit würde bei allen drei Wahrheitswerten im vorherigen Beispiel True herauskommen.
Caching von Zeichenketten (strings)
Genauso verhält es sich mit häufig verwendeten strings (Zeichenketten).
Für kurze Zeichenketten (strings) gilt die gleiche Erklärung für diese Anomalie, wie für ganze Zahlen. Manche strings werden so häufig verwendet, dass Python sie bereits fest im Cache-Speicher platziert hat und jede Variable, der so ein Wert zugeordnet wird, immer auf diesen Speicherort verweist.
Mein letztes Beispiel für strings, um noch mehr Klarheit zu schaffen.
string_1 = "Hallo"
string_2 = "Hallo"
print(string_1 is string_2)
string_3 = "MINT first."
string_4 = "MINT first."
print(string_3 is string_4)
True False
Im ersten Teil des Beispiels haben wir den string „Hallo“ betrachtet. Der kommt so häufig vor, dass Python diesen an einem fixen Ort „vorgespeichert“ hat. Und wann immer du einer Variable diesen Wert zuweist, wird sie auf diesen fixierten Speicherort zeigen und somit erhalten wir True für den ersten Ausdruck.
Dann haben wir den string „MINT first.“ betrachtet. Das ist keine sehr häufige Zeichenkette, Python hat noch nie davon gehört.
Deshalb wird jedes Mal, wenn einer Variable dieser Wert zugewiesen wird, ein neuer Speicherort definiert. Und deshalb erhalten wir als zweiten Ausdruck False.
Man kann sogar selbst Werte, die man häufig verwendet, in Python „internieren“. Somit sind sie schnell verfügbar und alle Variablen mit diesem Wert würden auf diesen Speicherort verweisen, aber das werde ich in diesem Beitrag nicht ausführen.
Ich hoffe, die Beispiele konnten dir etwas weiterhelfen. Die Identitätsoperatoren is und is not in Python und die Identitäts-Funktion id() können manchmal etwas verwirrend sein.
Auch haben wir gemerkt, dass die Ergebnisse von der Pythonversion, die du verwendest, stark abhängen. Am besten probierst du alle Beispiele einmal selbst aus. Für Tipps, welchen Online-Editor du verwenden kannst, damit du Python nicht herunterladen musst, habe ich hier einen Artikel für dich.
Lass gerne ein Kommentar da, wenn du Fragen oder Anmerkungen hast. Frag auch gerne nochmal nach, falls du etwas nicht verstanden hast. Mein Ziel ist es, komplizierte Dinge so einfach, wie möglich zu erklären. Das ist manchmal gar nicht so leicht mit all den Fachbegriffen, deshalb schreib mir gerne!
Sehr gute Einführung in Python , auch für einen älteren User (Rentner) der nicht mehr alles auf Anhieb begreift, aber mit viel Übung klappt es dann doch.
Wollte mich für den Newsletter anmelden , klappt aber leider nicht . Ich bekomme keine Rückmeldung per Mail , so dass ich leider meine Mail-Adresse nicht bestätigen kann. Sehr Schade.
Mal sehen , ob dieser Kommentar ankommt.
Hallo! Vielen Dank für den Kommentar. Das freut mich, dass meine Python-Erklärungen hilfreich sind. Bzgl. der Newsletter-Anmeldung weiß ich leider auch nicht woran es lag 🙁 gerne nochmal eine E-Mail an kontakt@mint-first.de schreiben, dass du gerne den Newsletter erhalten möchtest. Dann kann ich auch manuell die E-Mail-Adresse dem Mailverteiler hinzufügen. Liebe Grüße, Viktoria.