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 "==".
Besten Dank.
Welchen Operator soll ich benutzen? "==" oder "is"?
- 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
Offizielles Python-Tutorial (Deutsche Version)
Urheberrecht, Datenschutz, Informationsfreiheit: Piratenpartei
Urheberrecht, Datenschutz, Informationsfreiheit: Piratenpartei
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.
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.
Warum sollten sie? Porzellanteller kann man auch nicht verändern (nur kaputt machen), trotzdem sind zwei gleiche Teller nicht dieselben Objekte.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.
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
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.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.
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:
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.>>> a = 100
>>> b = 100
>>> a is b
True
>>> a = 1000
>>> b = 1000
>>> a is b
False
-
- Python-Forum Veteran
- Beiträge: 16025
- Registriert: Freitag 20. Juni 2003, 16:30
- Kontaktdaten:
Noch mehr Spaß mit Objektidentität:
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.
Code: Alles auswählen
>>> a = 42
>>> b = 42
>>> a is b
True
>>> c = 420
>>> d = 420
>>> c is d
False
Captain Obvious: Verschiedene Operatoren machen verschiedene Sachen.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
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
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
Stefan
- 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
In specifications, Murphy's Law supersedes Ohm's.
-
- 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!
Ist dieses Verhalten gewollt? Wenn ja warum?
Danke!
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.
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.