Klassen en objecten#

Het ontwerpen van data

Een geheel nieuwe klasse class van programmeren!

Bouwstenen#

  • functies

  • compositie

Een probleem opdelen in functies, waar elke functie verantwoordelijk is voor een deel van de oplossing. Je hebt niet alleen eigen functies geschreven, maar bedenk ook hoe vaak je ingebouwde functies als len, min, max hebt gebruikt als onderdeel van jouw composities!

Data#

De representatie van informatie: typen

  • string

  • int / float

  • list

En combinaties van typen als LoL’s!

Een Student ontwerpen#

Een student gaat studeren…

Van een student willen we informatie opslaan, laten we beginnen met naam en jaar van inschrijven.

student_naam = "Jan Janssen"
student_start_jaar= 2023

Binnen de opleiding ICT hebben we veel meer studenten dan 1. Het moet mogelijk zijn om informatie van meerdere studenten te gebruiken.

student1_naam = "Jan Janssen"
student1_start_jaar= 2023
student2_naam = "John Smith"
student2_start_jaar= 2023

Dit is onhandig, misschien is het mogelijk het in een lijst te plaatsen?

students = ["Jan Janssen", 2023, "John Smith", 2023 ]

Zodra we meerdere studenten hebben en ook andere informatie willen opslaan wordt het al snel onoverzichtelijk. Het wordt ook lastig om informatie te vinden van een specifieke student.

Elke student heeft een student nummer, wat handig kan zijn om een student te vinden. Bijvoorbeeld het vinden van de naam van student met nummer 463726

students = [463726, "Jan Janssen", 2023, 482638, "John Smith", 2023 ]
student_index = students.index(463726)
print(students[student_index+1])
Jan Janssen

In een lijst moeten we eerst de index weten van een element voordat we het uit de lijst kunnen halen. Het zou handig zijn als we de studentnummer als index kunnen gebruiken. Nadeel is dat het wel een hele lange lijst wordt, gezien student nummers grote getallen zijn. Daar is een oplossing voor: een Dictionary.

Dictionairy#

Dictionaries zijn willekeurige containers

d = {47: 2, 42: 1}

Elementen (of waarden) worden opgehaald met een sleutel op een willekeurige positie

d[47] == 2
d[42] == 1
students = {463726: ["Jan Janssen", 2023], 482638: ["John Smith", 2023] }
print(students[463726])
['Jan Janssen', 2023]
students = {463726: ["Jan Janssen", 2023], 482638: ["John Smith", 2023] }
print(students[463726][0])
Jan Janssen

Goed nieuws, sleutels kunnen ook andere typen dan int zijn!

student1 = {'naam':"Jan Janssen", 'start_jaar':2023}
student2 = {'naam':"John Smith", 'start_jaar':2023}
print(student1['naam'])
Jan Janssen

En net als een lijst lijsten kan bevatten, de zogenaamde LoL, kan een dictionary uit dictionaries bestaan.

students = {463726: {'naam':"Jan Janssen", 'start_jaar':2023}, 482638: {'naam':"John Smith", 'start_jaar':2023} }
print(students[463726]["naam"])
Jan Janssen

We kunnen informatie opslaan over studenten op deze manier, maar het blijft een dictonairy. Wat als we het data type student konden maken?

Klassen en objecten#

  1. Een klasse is een type

  2. Een object is een specifieke instantie van dat type

Alles in Python is een object (variabele) Wat het kan (functies, of “methoden”) wordt bepaald door de klasse (type)

s = str("Astronaut wordt snel oud tijdens een reis naar Mars")

De variabele s is een object, het is een instantie van de klasse str. In de * klasse* strstaat bijvoorbeeld de methode count(). Deze methode kan tellen hoe vaak een gegeven character voorkomt in de string.

s = str("Astronaut wordt snel oud tijdens een reis naar Mars")
print(s.count("e"))
5

Cookie cutter

Zie een type als een mal, waar er maar één van is, maar waar véél objecten (instanties) van kunnen worden gemaakt. De klasse definieert de “vorm”, een object is de concrete uitwerking van deze vorm (koekjes!).

Blauwdruk

Een klasse kan je ook zien als een blauwdruk of bouwtekening (een getedailleerde mal). Het definieert de eigenschappen van een object (een raket, een huis, …). Het beschrijft wat het is maar ook wat het kan (een raket kan vliegen, in een huis met keuken kan worden gekookt, …).

Een klasse Student ontwerpen#

We kunnen onze eigen klasse schrijven! M.a.w. een nieuwe type, waaronder dus het type Student.

class Student:
    """A class representing students
    """
    def __init__(self, name, yr):
        """The constructor
        """
        self.name = name
        self.start_year = yr

    def __repr__(self):
        """For printing
        """
        return self.name + " " + str(self.year)

    def delay(self, num_yrs):
        """Defer study for num_years
        """
        self.start_year += num_yrs

Objecten#

Een object is een structuur en bestaat uit data elementen en methodes(functies).

De student heeft een aantal data elementen en deze hebben namen (attributen, of velden):

  • naam

  • start_jaar

De student heeft functies (methoden) die het zelf kan gebruiken (maar ook wij!).:

  • __init__ de constructor. Deze methode wordt gebruikt om de student aan te maken. Elke klasse heeft deze methode nodig.

  • __repr__ een string representatie van het object, zodat de computer weet hoe het object geprint moet worden.

  • delay() is een methode om het inschrijfjaar aan te passen.

Methoden met dubbele underscores worden ook wel dunder methoden genoemd. Het is een conventie in Python om speciale methoden op deze manier te schrijven. Handig, want op deze manier zijn ze beter te ondescheiden van andere methoden (die jij gaat schrijven!).

class Student:
    """A class representing students
    """
    def __init__(self, name, yr):
        """The constructor
        """
        self.name = name
        self.year = yr

    def __repr__(self):
        """For printing
        """
        return "naam: "+ self.name + ", start jaar: " + str(self.year)

    def delay(self, num_yrs):
        """Defer study for num_years
        """
        self.year += num_yrs

Het is nu mogelijk om onze eigen studenten aan te maken.

student_a = Student("Peter Been", 2021)
student_b = Student("Jasper Klein", 2021)
student_c = Student("Linda Buitendijk", 2022)
student_d = Student("Myrthe Zomer", 2021)

Zodra je een student aanmaakt, of een andere data type, wordt eerst de constructor aangeroepen van het type. De print functie verwacht een string om te printen. Een student moet dan eerst omgezet worden tot een string en dan kan het geprint worden. De methode __repr__() kan daar gebruikt voor worden.

student_b.__repr__()
'naam: Jasper Klein, start jaar: 2021'

__repr__() is een dunder methoden en het is niet nodig of gebruikelijk om deze zelf aan te roepen. Het is een methode dat Python in de achtergrond gebruikt wanneer het nodig is. Zolang de methode __repr__() aanwezig is kan het object rechstreeks geprint worden. Python roept zelf de functie __repr__() om een Student te kunnen printen.

print(student_b)
naam: Jasper Klein, start jaar: 2021

Het is mogelijk om de data elementen van een object op te vragen.

student_b.name
'Jasper Klein'

En een object kan een methode uitvoeren.

student_b.delay(1)
student_b.year
2022
print(student_b)
naam: Jasper Klein, start jaar: 2022

Opgaven#

Opdracht 1#

a Voeg het data element student_nummer toe aan het type Student door de constructor methode aan te passen in de klasse Student
b Pas de functie __repr__() aan zodat het student nummer ook wordt geprint.