Objecten weergeven en vergelijken · oefening
Identiteit en gelijkheid verschillen
Twee vragen met precies dezelfde vraagtekst, hetzelfde antwoord en dezelfde punten. Zijn het dezelfde vraag?
False. Twee objecten die identiek lijken, door hun eigen repr identiek worden afgedrukt, en Python zegt dat ze niet gelijk zijn.
Wat == standaard doet
Zonder andere instructies stelt == op je eigen objecten een veel beperktere vraag dan je waarschijnlijk bedoelde. Het vraagt: zijn dit hetzelfde object?
first is second is False, omdat er twee afzonderlijke objecten zijn aangemaakt. third is first is True, omdat third = first een verwijzing bewaarde naar het object dat al bestond. Dit is het idee van twee namen voor één object uit hoofdstuk 4. Standaard geeft == precies hetzelfde antwoord als is.
Hier zitten twee verschillende ideeën achter, en Python houdt ze gescheiden. Het diagram noemt dit ‘Matching contents, different objects’: overeenkomende inhoud, verschillende objecten. ‘Question object A’ en ‘Question object B’ zijn twee afzonderlijke vraagobjecten; ‘default’ bij de vergelijking betekent dat het om het standaardgedrag gaat.
Identiteit vraagt of twee namen naar één object in het geheugen verwijzen.
isbeantwoordt die vraag en je kunt dit nooit zelf definiëren.Gelijkheid vraagt of twee objecten als dezelfde waarde moeten gelden.
==beantwoordt die vraag en die beslissing hoort bij de klasse.

In dit hoofdstuk willen we dubbele vraaginhoud herkennen. Voor die taak moeten vragen met overeenkomende vraagteksten, antwoorden en punten als gelijk worden vergeleken. Een ander quizsysteem zou elke opgestelde vraag een eigen identiteit kunnen geven en ze bewust afzonderlijk kunnen houden.
a = Question("Q", "A", 1) en b = a, daarna c = Question("Q", "A", 1). Wat is waar zonder een gedefinieerde __eq__?
Waar de standaard tegenwerkt
De standaard is niet alleen verrassend. Die maakt ongemerkt dingen stuk die je al hebt geschreven:
in meldt False en herkent een nieuw aangemaakte vraag dus niet als inhoudelijk duplicaat. Methoden zoals .remove() zouden in plaats daarvan ValueError opgooien als ze geen overeenkomst vinden. in, .index(), .remove(), .count() en list1 == list2 zijn allemaal gebouwd op == en nemen dus allemaal over wat de klasse heeft besloten.
Wanneer de standaard juist is
Voordat je die haastig verandert, bedenk dan dat de standaard vaker juist is dan het lijkt.
Voor een QuizAttempt zou gelijkheid op basis van inhoud verkeerd zijn. Twee cursisten die op dinsdag allebei 4 van de 10 punten haalden, deden niet dezelfde poging. Als de ene later wordt gecorrigeerd, mag de andere niet mee veranderen. Een poging is een gebeurtenis: die heeft een eigen identiteit en twee pogingen zijn alleen dezelfde als ze letterlijk één en dezelfde zijn.
Het onderscheid dat de doorslag geeft:
| Soort | Gelijk wanneer | Voorbeelden |
|---|---|---|
| Waardeobject | De inhoud overeenkomt | Question, een punt, een geldbedrag, een datum |
| Entiteit | Ze één en dezelfde zijn | QuizAttempt, een cursist, een bestelling, een sessie |
Waardegelijkheid behandelt overeenkomende inhoud als uitwisselbaar bij vergelijkingen. Het zorgt er niet voor dat twee objecten latere wijzigingen delen. In de volgende oefening gebruiken we alleen-lezen vraagtoestand om dit waardemodel makkelijker te bewaren. Entiteiten zijn niet uitwisselbaar: attempt_a en attempt_b zijn twee dingen die zijn gebeurd, hoe sterk ze ook op elkaar lijken.
De volgende les definieert gelijkheid voor de waardeobjecten. Deze les zorgt ervoor dat je het onderscheid kunt maken, omdat waardegelijkheid op een entiteit gebeurtenissen ongemerkt kan samenvoegen die afzonderlijk moeten blijven.
Opdracht
Ontdek wat het huidige gedrag werkelijk is voordat je verandert hoe iets wordt vergeleken.
Maak de drie functies af met alleen wat Python nu al doet. Geen van deze klassen definieert al __eq__.
same_object(a, b)meldt of twee namen naar één object verwijzen.default_equal(a, b)meldt wat==er nu over zegt.found_in(bank, wanted)meldt metinof er een vraag gelijk aanwantedin de lijst staat.
Het onderscheid tussen waardeobjecten en entiteiten is een ontwerpbeslissing, geen truc om strings aan elkaar te koppelen, en blijft daarom in de uitgewerkte bespreking. De oefening richt zich op het waarnemen van de drie Pythonbewerkingen die het onderscheid zichtbaar maken.