0%

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?

Try it

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?

Try it

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. is beantwortet 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.

Zwei getrennt erzeugte Question-Objekte haben gleiche Fragetexte, erwartete Antworten und Punkte, aber unterschiedliche Identitäten. Ein Alias verweist auf das erste Objekt und teilt dessen Identität.

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:

Try it

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:

ArtGleich, wennBeispiele
WertobjektDie Inhalte übereinstimmenQuestion, ein Punkt, ein Geldbetrag, ein Datum
EntitätEs dasselbe Objekt istQuizAttempt, 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 mit in, ob eine zu wanted gleiche 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.