droptix hat geschrieben:Uh, was ist der genaue Unterschied zwischen Gleicheit und Identität?
Das ist der Unterschied zwischen "das selbe" und "das gleiche", den es laut Duden im deutschen leider nicht mehr gibt.
Mit ``is`` testet man, ob es sich tatsächlich um das selbe Objekt handelt. Es gibt also nur ein einziges Objekt, das diese Eigenschaft erfüllt. Mit ``==`` testet man auf Gleichheit, was nicht so scharf definiert ist, bzw. in Python vom Programmierer festgelegt werden kann. Beispiel:
Code: Alles auswählen
In [38]: a = 1
In [39]: b = 1.0
In [40]: type(a), type(b)
Out[40]: (<type 'int'>, <type 'float'>)
In [41]: a is b
Out[41]: False
In [42]: a == b
Out[42]: True
`a` und `b` sind ganz offensichtlich zwei verschiedene Objekte, sogar von unterschiedlichem Typ, aber der Wert ist gleich.
`True` und `False` gab es früher in Python nicht, darum haben sich viele Leute in ihren Modulen die Namen `True` und `False` an "wahre"/"falsche" Werte gebunden, z.B. 1 und 0, um den Quelltext lesbarer zu machen. Deshalb kann es verschiedene `True`-Objekte in einem Programm geben, die mit ``is`` verglichen, "falsch" ergeben aber mit ``==`` "wahr" sind.
In [43]: 1 is True
Out[43]: False
In [44]: 1 == True
Out[44]: True
Auf Identität sollte man wirklich nur prüfen, wenn man exakt ein ganz bestimmtes Objekt erwartet. Das ist bei `None` gegeben, weil `None` ein Singleton ist, also ein Objekt von dem es nur ein Exemplar gibt, und der Name `None` auch nicht an andere Objekte gebunden werden kann:
Code: Alles auswählen
In [45]: None = "hallo"
------------------------------------------------------------
SyntaxError: assignment to None
Ansonsten kann man ``is`` noch in Graphenalgorithmen verwenden um zum Beispiel festzustellen, ob man bei einem Objekt, und genau dem Objekt, schon einmal vorbeigekommen ist, oder um bei Algorithmen den Knoten auf dem die Methode ausgeführt wird auszuschliessen, indem man auf ``is not self`` testet.
Eine weitere Einsatzmöglichkeit sind "Sentinel"-Objekte, deren einziger Zweck es ist, in einem Identitätsvergleich verwendet zu werden. Zum Beispiel wenn man eine Funktion schreibt, die ein optionales Argument erhält, welches wirklich jeden Wert annehmen darf, also auch `False`, `None` und so weiter, aber nur berücksichtigt werden soll, wenn es beim Aufruf angegeben wurde. Das kann man z.B. so lösen:
Code: Alles auswählen
NOTHING = object() # Absolut einzigartiges Objekt
def spam(eggs, opt=NOTHING):
# ...
if opt is not NOTHING:
# ...
# ...