0%

Objecten weergeven en vergelijken · eindproject

Eindproject: Project: maak quizobjecten duidelijk en vergelijkbaar

Dit hoofdstuk gaf je vijf methoden en, nog nuttiger, regels over wanneer elke methode op haar plek is. Het project is vooral een oefening in terughoudendheid: drie van de vier klassen horen minder methoden te krijgen dan je misschien geneigd bent toe te voegen.

De beslissingen

KlasseWat het isKrijgt
PointsEen alleen-lezen waarde met een natuurlijke volgorde__repr__, __eq__, __hash__, __lt__
QuestionEen alleen-lezen waarde zonder natuurlijke volgorde__repr__, __str__, __eq__, __hash__
ResponseEen waarde die alleen ontwikkelaars zien__repr__, __eq__
QuizAttemptEen gebeurtenis met een eigen identiteit__repr__, __str__

Bij twee hiervan is het de moeite waard even stil te staan.

Points en Question houden elk attribuut dat hun hashes gebruiken alleen-lezen. Als een van die waarden na opname in een set zou kunnen veranderen, kan het opzoeken mislukken hoewel het object nog aanwezig is.

Response krijgt __eq__ maar geen __hash__. De vraag en de gegeven tekst veranderen niet, maar een antwoord wordt nooit als dictionarysleutel gebruikt of in een set gezet. Een __hash__ toevoegen die niets nodig heeft, is een belofte die voor altijd correct te houden zonder er iets voor terug te krijgen.

QuizAttempt definieert noch __eq__ noch __hash__ en behoudt dus Pythons standaardgelijkheid op basis van identiteit en de bijbehorende hash. Twee pogingen van dezelfde cursist met dezelfde score zijn afzonderlijke gebeurtenissen. Hun antwoorden mogen veranderen zonder die identiteit of hash te veranderen; een hash op basis van die veranderende inhoud zou onveilig zijn.

Waarom zou het hier een fout zijn om QuizAttempt een op inhoud gebaseerde __eq__ te geven?

Wat het programma doet

Het aansturende programma maakt een kleine vragenbank met één duplicaat, verwijdert dat duplicaat met een set, sorteert wat overblijft op punten, voert één poging uit en drukt een rapport af. Elke stap steunt op iets uit dit hoofdstuk en niets daarvan werkt met het standaardgedrag dat Python aan een nieuwe klasse geeft.

Afronden

Lees je voltooide klassen en toets elke methode aan één vraag: wat zou stukgaan als deze werd verwijderd? Als er niets stuk zou gaan, verwijder die dan. __hash__ op een klasse die nooit een sleutel is, __str__ die alleen de repr herhaalt en __lt__ op iets zonder duidelijke volgorde zijn allemaal code die moet worden onderhouden en niets oplevert.

Voeg ten slotte één duplicaat en één nieuwe eigen vraag aan de bank toe. In het afgedrukte resultaat moet het duplicaat verdwijnen, moet de nieuwe vraag op de juiste plek volgens het puntenaantal staan en moet alles leesbaar blijven zonder een van beide antwoorden prijs te geven.

Opdracht

Voeg de speciale methoden uit de tabel in de les toe. Houd de gegeven publieke bewerkingen werkend; kleine hulpmethoden zijn welkom.

Points: alleen-lezen hoeveelheid; repr Points(3); gelijk, hashbaar en geordend op basis van de hoeveelheid.

Question: alleen-lezen vraagtekst, antwoord en punten; repr Question('...', '...', Points(2)); str <prompt> (2 points), die het antwoord niet mag onthullen; gelijk en hashbaar op basis van vraagtekst, antwoord en punten.

Response: alleen-lezen vraag, gegeven tekst en momentopnamen van juistheid, beschikbare punten en verdiende punten; repr Response(given='3', earned=2); gelijk op basis van de vraag en de gegeven tekst. Geen __hash__.

QuizAttempt: overzichtsrepr QuizAttempt(learner='Mina', response_count=2); str Mina: 4 points. Geen overschrijving van __eq__ en geen overschrijving van __hash__: behoud het geërfde identiteitsgedrag.

Schrijf vervolgens unique_sorted(questions), dat de unieke vragen teruggeeft met de goedkoopste eerst. Gebruik een set om duplicaten te verwijderen en een sleutelfunctie om te sorteren, omdat geen van beide beslissingen binnen Question hoort.

Elke __eq__ moet NotImplemented teruggeven voor een ander type.