Objekte darstellen und vergleichen · Übung
Identität und Gleichheit unterscheiden
Zwei Fragen mit exakt demselben Fragetext, derselben erwarteten Antwort und denselben Punkten. Sind sie dieselbe Frage?
False. Zwei Objekte, die identisch aussehen und von ihrer eigenen repr-Darstellung identisch ausgegeben werden. Trotzdem sagt Python, sie seien nicht gleich.
Was == standardmäßig tut
Ohne eine andere Vorgabe stellt == bei deinen eigenen Objekten eine viel engere Frage, als du wahrscheinlich meinst: Ist es dasselbe Objekt?
first is second ist False, weil zwei getrennte Objekte erzeugt wurden. third is first ist True, weil third = first eine Referenz auf das bereits vorhandene Objekt gespeichert hat. Das ist die Idee „zwei Namen für ein Objekt“ aus Kapitel 4. Standardmäßig gibt == genau dieselbe Antwort wie is.
Hier stecken zwei verschiedene Konzepte, die Python getrennt hält:
Identität fragt, ob zwei Namen auf ein Objekt im Speicher verweisen.
isbeantwortet diese Frage, und das kannst du nicht selbst definieren.Gleichheit fragt, ob zwei Objekte als derselbe Wert gelten sollen.
==beantwortet diese Frage. Diese Entscheidung gehört zur Klasse.

In diesem Kapitel wollen wir doppelte Frageinhalte erkennen. Dafür sollen Fragen mit übereinstimmenden Fragetexten, erwarteten Antworten und Punkten als gleich gelten. Ein anderes Quizsystem könnte jeder verfassten Frage eine eigene Identität geben und sie bewusst auseinanderhalten.
Nach a = Question("Q", "A", 1) und b = a folgt c = Question("Q", "A", 1). Was gilt, wenn kein __eq__ definiert ist?
Wo der Standard Probleme macht
Der Standard ist nicht nur überraschend. Er lässt Dinge, die du schon geschrieben hast, unbemerkt falsch arbeiten:
in meldet False und erkennt eine frisch erzeugte Frage somit nicht als inhaltliches Duplikat. Methoden wie .remove() würden dagegen ValueError auslösen, wenn sie keine Übereinstimmung finden. in, .index(), .remove(), .count() und list1 == list2 bauen alle auf == auf und übernehmen daher die Entscheidung der Klasse.
Wann der Standard richtig ist
Bevor du ihn vorschnell änderst, beachte, dass der Standard häufiger richtig ist, als es aussieht.
Bei einem QuizAttempt wäre Gleichheit nach Inhalt falsch. Zwei Lernende, die beide am Dienstag 4 von 10 Punkten erreicht haben, haben nicht denselben Versuch unternommen. Wird einer später korrigiert, darf sich der andere dadurch nicht ändern. Ein Versuch ist ein Ereignis: Er hat eine eigene Identität. Zwei Versuche sind nur dann derselbe, wenn sie buchstäblich dasselbe Objekt sind.
Entscheidend ist diese Unterscheidung:
| Art | Gleich, wenn | Beispiele |
|---|---|---|
| Wertobjekt | Die Inhalte übereinstimmen | Question, ein Punkt, ein Geldbetrag, ein Datum |
| Entität | Es dasselbe Objekt ist | QuizAttempt, eine lernende Person, eine Bestellung, eine Sitzung |
Wertgleichheit behandelt übereinstimmende Inhalte für Vergleiche als austauschbar. Sie bewirkt nicht, dass zwei Objekte spätere Änderungen teilen. In der nächsten Übung verwenden wir schreibgeschützten Fragezustand, damit sich dieses Wertmodell leichter erhalten lässt. Entitäten sind nicht austauschbar: attempt_a und attempt_b sind zwei geschehene Dinge, wie ähnlich sie auch aussehen.
Die nächste Lektion definiert Gleichheit für Wertobjekte. Diese Lektion soll sicherstellen, dass du Wertobjekte und Entitäten unterscheiden kannst. Eine Entität mit Wertgleichheit auszustatten kann Ereignisse unbemerkt zusammenführen, die getrennt bleiben müssen.
Aufgabe
Bevor du Vergleiche veränderst, finde heraus, wie sie sich derzeit tatsächlich verhalten.
Vervollständige die drei Funktionen mit dem, was Python aktuell tut. Keine dieser Klassen definiert bereits __eq__.
same_object(a, b)meldet, ob zwei Namen auf ein Objekt verweisen.default_equal(a, b)meldet, was==derzeit über sie aussagt.found_in(bank, wanted)meldet mitin, ob eine zuwantedgleiche Frage in der Liste enthalten ist.
Die Unterscheidung zwischen Wertobjekt und Entität ist eine Entwurfsentscheidung, kein Trick zum Zuordnen von Strings. Sie bleibt daher Teil der besprochenen Beispiele. Die Übung konzentriert sich auf die drei Python-Operationen, die den Unterschied sichtbar machen.