Welchen Operator soll ich benutzen? "==" oder "is"?

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
Dingels
User
Beiträge: 61
Registriert: Dienstag 23. Dezember 2008, 19:50

Hi Leute,

ich habe ein Programm geschrieben, in dem sehr viele Strings auf ihren Inhalt hin überprüft werden. Bisher habe ich dafür immer den "=="-Operator verwendet. Ist es schlechter Stil, wenn man stattdessen den "is"-Operator nimmt? In PEP 8 konnte ich dazu nichts finden. Ich kenne den Unterschied zwischen beiden Operatoren und weiß, dass "is" die Identität zweier Objekte vergleicht und "==" nur die Gleichheit der Inhalte der Objekte. Aber da ich nur Strings auf ihre Inhalte hin überprüfe und Strings zu den unveränderlichen Datentypen gehören, würde der "is"-Operator dieselben Ergebnisse liefern. Ich frage das deshalb, weil der "is"-Operator einfach schöner zu lesen ist als "==". :mrgreen:

Besten Dank. :)
Benutzeravatar
Rebecca
User
Beiträge: 1662
Registriert: Freitag 3. Februar 2006, 12:28
Wohnort: DN, Heimat: HB
Kontaktdaten:

Code: Alles auswählen

>>> s1 = "hallo welt bla bla bla bla bla!"
>>> s2 = "hallo welt bla bla bla bla bla!"
>>> s1 is s2
False
Auch immutable Objekte koennen den gleichen Inhalt haben und doch verschiedene Objekte sein! Genau genommen optimiert CPython zwar einige Strings und Integer, sodass man hier evtl tatsaechlich Objektidentitaet hat, das ist aber ein Implementierungsdetail, worauf man sich nicht verlassen sollte!
Offizielles Python-Tutorial (Deutsche Version)

Urheberrecht, Datenschutz, Informationsfreiheit: Piratenpartei
Dingels
User
Beiträge: 61
Registriert: Dienstag 23. Dezember 2008, 19:50

Hallo Rebecca,

vielen Dank für die prompte Antwort. Tolles Forum hier. :) Aber das habe ich tatsächlich noch nicht gewusst. Ich dachte, unveränderliche Datentypen haben immer dieselbe Identität. Das Verhalten find ich irgendwie doof. Aber ok, dann hab ich mit dem "=="-Operator ja alles richtig gemacht.

Danke nochmals und schönen Sonntag noch. :)
ms4py
User
Beiträge: 1178
Registriert: Montag 19. Januar 2009, 09:37

Noch als Ergänzung: "None" prüft man normalerweise mit `is`
„Lieber von den Richtigen kritisiert als von den Falschen gelobt werden.“
Gerhard Kocher

http://ms4py.org/
Darii
User
Beiträge: 1177
Registriert: Donnerstag 29. November 2007, 17:02

Dingels hat geschrieben:Aber das habe ich tatsächlich noch nicht gewusst. Ich dachte, unveränderliche Datentypen haben immer dieselbe Identität. Das Verhalten find ich irgendwie doof.
Warum sollten sie? Porzellanteller kann man auch nicht verändern (nur kaputt machen), trotzdem sind zwei gleiche Teller nicht dieselben Objekte.
Dav1d
User
Beiträge: 1437
Registriert: Donnerstag 30. Juli 2009, 12:03
Kontaktdaten:

Was noch nicht erwähnt wurde:

Code: Alles auswählen

>>> s1 = 'ein string'
>>> s2 = 'ein string'
>>> s3 = s1
>>> s1 is s2
False
>>> s2 is s3
False
>>> s1 is s3
True
the more they change the more they stay the same
Barabbas
User
Beiträge: 349
Registriert: Dienstag 4. März 2008, 14:47

Dingels hat geschrieben:Aber das habe ich tatsächlich noch nicht gewusst. Ich dachte, unveränderliche Datentypen haben immer dieselbe Identität. Das Verhalten find ich irgendwie doof.
Da bringst du jetzt aber etwas durcheinander: Das Beispiel von Rebecca demonstriert nicht Unveränderlichkeit. Es demonstriert, wie zwei String-Objekte erstellt werden, die die gleiche Zeichenkette beinhalten (bitte korrigiert mich, wenn ich das nicht richtig ausdrücke). Das ist eigentlich immer so. Es gibt sicher auch nur wenig Fälle, in denen du möchtest, dass unabhängig voneinander erstellte Objekte miteinander identisch sind. Das würde in den meisten Fällen sicher zu Fehlern führen, die kaum nachzuvollziehen wären.

Unveränderlichkeit beschreibt nur was passiert, wenn du irgendein Objekt veränderst. Ein unveränderliches Objekt lässt sich nicht verändern, so dass immer ein ganz neues Objekt mit dem neuen Inhalt erstellt werden muss.

@Dav1d:
Naja, das ist ja selbstverständlich. Alles andere fände ich äußerst verwunderlich. Interessanter finde ich da schon dieses Beispiel:
>>> a = 100
>>> b = 100
>>> a is b
True
>>> a = 1000
>>> b = 1000
>>> a is b
False
Sehr verwirrender Effekt, hängt aber (wenn ich das richtig in Erinnerung habe) nur damit zusammen, dass Python Int-Objekte für die Zahlen von 0 - 100 beim Start generiert und bei Bedarf nur noch Verweise auf diese Objekte rausrückt.
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Noch mehr Spaß mit Objektidentität:

Code: Alles auswählen

>>> a = 42
>>> b = 42
>>> a is b
True
>>> c = 420
>>> d = 420
>>> c is d
False
Bei CPython ist es nämlich so dass die Integer bis 100 gecached werden und wenn man so ein Objekt erstellen will, ein bereits existierendes Integer-Objekt zurückgegeben wird. Ab 100 sieht es dann schon anders aus.

Captain Obvious: Verschiedene Operatoren machen verschiedene Sachen. :twisted:
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
BlackJack

Und noch ein bisschen Gedankenfutter:

Code: Alles auswählen

In [1493]: a = 'Hallo'

In [1494]: b = 'Hallo'

In [1495]: a is b
Out[1495]: True

In [1496]: a = 'Hallo Welt'

In [1497]: b = 'Hallo Welt'

In [1498]: a is b
Out[1498]: False

In [1499]: a = 'Hallo Welt'; b = 'Hallo Welt'

In [1500]: a is b
Out[1500]: True
sma
User
Beiträge: 3018
Registriert: Montag 19. November 2007, 19:57
Wohnort: Kiel

Mit anderen Worten: `is` sollte man nur benutzen, wenn man Objektidentitäten vergleichen will, ansonsten lieber immer `==`, was Gleichheit prüft. Identische Objekte sind in der Regel (eigentlich fällt mir keine Ausnahme ein) gleich, aber gleiche Objekte müssen nicht identisch sein.

Stefan
Benutzeravatar
pillmuncher
User
Beiträge: 1484
Registriert: Samstag 21. März 2009, 22:59
Wohnort: Pfaffenwinkel

@sma:

Code: Alles auswählen

import time

class Foo(object):
    def stupid(self):
        time.sleep(.05)
        return time.time()
    def __eq__(self, other):
        return self.stupid() == other.stupid()

x = y = Foo()
print x is y
print x == y
:twisted:
In specifications, Murphy's Law supersedes Ohm's.
Darii
User
Beiträge: 1177
Registriert: Donnerstag 29. November 2007, 17:02

sma hat geschrieben:Identische Objekte sind in der Regel (eigentlich fällt mir keine Ausnahme ein) gleich
float-NaNs. NaN ist immer ungleich zu allem.
philistion
User
Beiträge: 108
Registriert: Sonntag 7. Februar 2010, 14:16

Hallo BlackJack, dein Beispiel verwirrt mich jetzt. Könntest du die Effekte bei 1495 und 1500 näher ausführen?
Ist dieses Verhalten gewollt? Wenn ja warum?

Danke!
BlackJack

Da Verhalten ist gewollt, aber eben ein Implementierungsdetail, man darf sich nicht darauf verlassen! Das muss nicht so sein.

Ad 1495: Alles was sich an die Regeln für gültige Bezeichner in Python-Quelltext hält, also zum Beispiel "Hallo" wird intern noch einmal vermerkt und neue literale Zeichenketten werden gegen diese interne Buchführung überprüft und nur einmal angelegt. Ganz einfach weil Attribute auf Objekten ja intern als Dictionaries, die Zeichenketten auf Objekte abbilden, gespeichert werden. Wenn man dafür sorgt, dass Bezeichner möglichst nur einmal im Speicher angelegt werden, spart man Speicherplatz und der Vergleich zwischen solchen Zeichenketten kann schneller implementiert werden weil gleiche `id()` auf jeden Fall auch gleicher Wert bedeuten.

Ad 1500: Bei Eingabe 1499 sieht der Compiler beide Zuweisungen und Literale auf einmal und erkennt, dass die Literale den gleichen Wert haben. CPython schaut also innerhalb einer Übersetzungseinheit, im normalen Betrieb ist das ein Modul, ob Zeichenketten mehrfach vorkommen und legt in dem Fall nur *eine* an. Das kann man bei "immutable" Objekten ja machen ohne die Semantik zu ändern.
Antworten