← Python/Eigen typen
Les 1 van 8
MODULE 07 · 01◷ 24 min

Klassen en afzonderlijke instanties

Na deze les kun je
  • Een klasse en haar afzonderlijke instanties onderscheiden.
  • Attributen op echte objecten lezen en veranderen.
  • Twee objecten onderscheiden van twee verwijzingen naar hetzelfde object.

Een naamkaartje heeft tekst die je kunt lezen en aanpassen. Zodra je meerdere kaartjes gebruikt, wil je hun gegevens bij elkaar houden en duidelijk herkennen welk soort ding je voor je hebt. Je maakte in de vorige module al een eigen foutklasse; nu beschrijf je zelf gewone gegevensobjecten.

Een soort en zijn exemplaren

Een klasse beschrijft een soort object. Een instantie is een concreet exemplaar van die klasse. Met Card() vraag je een nieuw exemplaar van de klasse Card aan, zoals je met [] een nieuwe lijst maakt.

Een lege klassedefinitie kan voorlopig pass als inhoud hebben. De klasse heeft daarmee een geldig blok, ook al voeg je nog geen eigen gedrag toe. Je kunt daarna gegevens aan de gemaakte instantie hangen.

Zo'n benoemde eigenschap heet een attribuut. Met de puntnotatie card.name lees je het attribuut name van dat ene kaartje. Een toekenning zoals card.name = "Ada" bewaart de tekst bij de instantie waarnaar card verwijst.

Twee echte kaartjes

Het voorbeeld maakt twee objecten en geeft ze ieder een eigen naam. Voorspel of het aanpassen van het eerste kaartje de naam op het tweede verandert. Let ook op de ronde haakjes bij iedere nieuwe instantie.

Twee instanties met eigen attributen
class Card:
    pass

first = Card()
first.name = "Ada"
second = Card()
second.name = "Bo"
print(first.name, second.name)
first.name = "Ana"
print(first.name, second.name)
Verwachte uitvoer
Ada Bo
Ana Bo

De variabelen bewaren verwijzingen naar de twee objecten. De namen van de variabelen zijn geen attribuutnamen: first kan bijvoorbeeld verwijzen naar een kaartje waarvan name de tekst Ada bevat. Je kiest die twee namen om verschillende dingen te beschrijven.

Dit is de situatie vóór de wijziging:

Naam in het programmaObjectAttribuut name
firstEerste kaartjeAda
secondTweede kaartjeBo

Deze tabel lijkt op het onderscheid tussen een lijst en de variabelen die naar haar verwijzen. Je nieuwe klasse verandert die verwijzingsregels niet. Zij geeft het object vooral een herkenbaar type en ruimte voor zijn eigen benoemde toestand.

Twee namen kunnen één object aanwijzen

Een toekenning alias = first maakt geen nieuw kaartje. Beide namen verwijzen dan naar dezelfde instantie. Dat wordt zichtbaar zodra je via één naam een attribuut wijzigt.

Een tweede naam blijft hetzelfde object
class Card:
    pass

first = Card()
first.name = "Oud"
alias = first
alias.name = "Nieuw"
print(first.name)
print(alias.name)
print(first is alias)
Verwachte uitvoer
Nieuw
Nieuw
True

Gebruik is wanneer je wilt weten of twee verwijzingen hetzelfde object aanwijzen. Twee afzonderlijke kaartjes kunnen dezelfde tekst hebben en toch verschillende objecten zijn. Gelijkheid op basis van eigen gegevens komt later in deze module aan bod.

Veelgemaakte fout: de klasse aanpassen

De naam Card verwijst naar de klasse zelf; Card() maakt een instantie. Een toekenning aan Card.name zet een waarde bij de klasse. Instanties zonder eigen name kunnen die gedeelde waarde zien, waardoor verschillende kaartjes onbedoeld dezelfde tekst krijgen.

Hang objectgebonden gegevens daarom aan de gemaakte instantie. In de opdrachten is Label het type en is bijvoorbeeld label één exemplaar. Met een nieuw Label() en daarna label.text = text geef je ieder kaartje een eigen attribuut.

Jouw naamkaartjes gebruiken

Je schrijft gewone functies die met echte Label-instanties werken. new_label maakt een kaartje, read_label leest zijn tekst en rename verandert het meegegeven object. Die laatste functie geeft None terug; de verandering is zichtbaar via de bestaande verwijzing van de aanroeper.

two_labels maakt twee onafhankelijke objecten en geeft ze samen als tuple terug. Ook bij twee gelijke teksten moeten het twee kaartjes blijven. Bewaar tekst precies zoals ontvangen, inclusief lege tekst, spaties en Unicode; deze les voegt geen opschoonregel toe.

AAN DE SLAG 0/4
1

Een echte instantie maken

Definieer Label als eenvoudige klasse en maak new_label(text). Geef een nieuwe Label-instantie met een eigen text-attribuut terug. Bewaar de tekst precies; een later nieuw kaartje mag een eerder kaartje niet wijzigen.

2

Een attribuut lezen

Maak read_label(label) die de text van de ontvangen Label-instantie teruggeeft. Bewaar de inhoud inclusief lege tekst, spaties en Unicode. Laat het ontvangen object ongewijzigd.

3

Het ontvangen object wijzigen

Maak rename(label, text) die de text van dezelfde ontvangen instantie wijzigt en None teruggeeft. De aanroeper moet de wijziging via zijn bestaande verwijzing kunnen zien.

4

Twee onafhankelijke exemplaren

Maak two_labels(first, second) die twee afzonderlijke Label-instanties met de opgegeven teksten maakt en als tuple teruggeeft. Ook gelijke teksten horen bij twee verschillende objecten.

Onthoud dit

  • Een klasse is een type; iedere aanroep van de klasse maakt hier een nieuwe instantie.
  • Attributen bewaren gegevens bij een object en worden via een punt gelezen of gezet.
  • Een tweede variabelenaam kopieert een verwijzing, niet het object.

Hierna laat je nieuwe objecten hun beginwaarden zelf instellen met __init__.

main.py
UitvoerPython
›
›_

Hier komt je resultaat.

Voer je code uit en ontdek
wat je hebt gemaakt.

0/4 stappen
EVEN MEEKIJKEN

Bekijk hoe het kan.

Je mag de oplossing bekijken. Deze poging telt dan niet mee als afgeronde les. Met Reset kun je daarna opnieuw zelf oefenen.