12. De klassen en objecten
De klasse is de mal waaruit objecten worden gemaakt. Van het object wordt gezegd dat het een instantie van een klasse is.

Opmerking: het bestand [shared] is in de map [Sources Root] van het project geplaatst.
12.1. script [classes_01]: een klasse Object
Het script [classes_01] toont een verouderd gebruik van klassen:
# een klasse
class Objet(object):
"""une classe Objet vide"""
# elke variabele van het type [Objet] kan per definitie attributen hebben
obj1 = Objet()
obj1.attr1 = "un"
obj1.attr2 = 100
# geeft het object weer
print(f"objet1=[{obj1}, {type(obj1)},{id(obj1)},{obj1.attr1},{obj1.attr2}]")
# wijzigt het object
obj1.attr2 += 100
# geeft het object weer
print(f"objet1=[{obj1.attr1},{obj1.attr2}]")
# wijst de referentie obj1 toe aan obj2
obj2 = obj1
# wijzigt het object waarnaar obj2 verwijst
obj2.attr2 = 0
# geeft beide objecten weer – obj1 verwijst nu naar een gewijzigd object
print(f"objet1=[{obj1.attr1},{obj1.attr2}]")
print(f"objet2=[{obj2.attr1},{obj2.attr2}]")
# obj1 en obj2 verwijzen naar hetzelfde object
print(f"objet1=[{obj1}, {id(obj1)},{obj1.attr1},{obj1.attr2}]")
print(f"objet2=[{obj2}, {id(obj2)},{obj2.attr1},{obj2.attr2}]")
print(obj1 == obj2)
# type van de instantie obj1
print(f"type(obj1)={type(obj1)}")
print(f"isinstance(obj1,Objet)={isinstance(obj1, Objet)}, isinstance(obj1,object)={isinstance(obj1, object)}")
# elk type is een object in Python
print(f"type(4)={type(4)}")
print(f"isinstance(4, int)={isinstance(4, int)}, isinstance(4, object)={isinstance(4, object)}")
Opmerkingen:
- regels 2-3: een lege klasse [Objet];
- regel 2: de klasse kan op drie manieren worden gedeclareerd:
- class Object;
- class Object();
- class Object(object);
- regel 3: een andere vorm van commentaar. Dit commentaar, voorafgegaan door drie "", kan over meerdere regels lopen;
- regel 7: instantiatie van de klasse Objet. Het resultaat is een adres, zoals te zien is in de regels 24-26;
- regels 8-9: directe initialisatie van twee attributen van het object;
- regel 17: kopiëren van verwijzingen. De variabelen obj1 en obj2 zijn twee pointers (verwijzingen) naar hetzelfde object;
- regel 19: het object waarnaar [obj2] verwijst, wordt gewijzigd. Aangezien [obj1] en [obj2] naar hetzelfde object verwijzen, zal uit de weergaven van de objecten [obj1, obj2] in de regels 21 en 22 blijken dat het object waarnaar [obj1] verwijst, is gewijzigd;
- regels 24-26: deze regels zijn bedoeld om aan te tonen dat de variabelen [obj1] en [obj2] gelijk zijn. Dit wordt duidelijk wanneer regel 26 wordt weergegeven. In deze vergelijking zijn de adressen [obj1] en [obj2] gelijk;
- elk Python-object wordt geïdentificeerd door een uniek nummer dat wordt verkregen met de uitdrukking [id(objet)]. De regels 24 en 25 laten zien dat de nummers van de objecten waarnaar [obj1] en [obj2] verwijzen, identiek zijn, wat aantoont dat deze twee verwijzingen naar hetzelfde object verwijzen;
- regels 27-29: de functie [isinstance(expr,Type)] retourneert de booleaanse waarde True als de uitdrukking [expr] van het type [Type] is. Hier zullen we zien dat [obj1] van het type [Objet] is, wat logisch lijkt, maar ook van het type [object]. De klasse [object] is de bovenliggende klasse van alle Python-klassen. Door de eigenschap van klasse-overerving heeft een dochterklasse F alle eigenschappen van haar bovenliggende klasse P en geeft de functie [isinstance(instance de F, P)] ‘True’ terug;
- regels 30-32: laten zien dat het type [int] ook een type [object] is. Alle Python-typen zijn afgeleid van de klasse [object];
Resultaten
C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\venv\Scripts\python.exe C:/Data/st-2020/dev/python/cours-2020/python3-flask-2020/classes/01/classes_01.py
objet1=[<__main__.Objet object at 0x0000025C3F469BB0>, <class '__main__.Objet'>,2595221838768,un,100]
objet1=[un,200]
objet1=[un,0]
objet2=[un,0]
objet1=[<__main__.Objet object at 0x0000025C3F469BB0>, 2595221838768,un,0]
objet2=[<__main__.Objet object at 0x0000025C3F469BB0>, 2595221838768,un,0]
True
type(obj1)=<class '__main__.Objet'>
isinstance(obj1,Objet)=True, isinstance(obj1,object)=True
type(4)=<class 'int'>
isinstance(4, int)=True, isinstance(4, object)=True
Process finished with exit code 0
12.2. Script [classes_02]: een klasse Personne
Het script [classes_02] laat zien dat de attributen van een klasse openbaar zijn: ze zijn rechtstreeks toegankelijk van buiten de klasse. Ook hier is sprake van een af te raden gebruik van klassen. We geven dit voorbeeld niettemin omdat dit soort code soms voorkomt (Python accepteert het) en je het dan moet kunnen begrijpen.
# klasse Personne
class Personne:
# attributen van de klasse
# niet gedeclareerd – kunnen dynamisch worden aangemaakt
# methode
def identité(self: object) -> str:
# gebruikt a priori niet-bestaande attributen
return f"[{self.prénom},{self.nom},{self.âge}]"
# ---------------------------------- main
# de attributen zijn openbaar en kunnen dynamisch worden aangemaakt
# klasse-instantiëring
p = Personne()
# directe initialisatie van attributen van de klasse
p.prénom = "Paul"
p.nom = "de la Hûche"
p.âge = 48
# aanroep van een methode van de klasse
print(f"personne={p.identité()}")
# type van de instantie p
print(f"type(p)={type(p)}")
print(f"isinstance(Personne)={isinstance(p, Personne)}, isinstance(object)={isinstance(p, object)}")
Opmerkingen:
- regels 2-9: een klasse met één methode;
- regel 7: elke methode van een klasse moet als eerste parameter het object self hebben, dat het huidige object aanduidt. De methode [identité] retourneert een tekenreeks;
- regel 15: instantiëren van een object [Personne];
- regels 16-19: laten zien dat de attributen van het object dynamisch kunnen worden aangemaakt (ze komen niet voor in de definitie van de klasse);
- regel 9: de attributen van de klasse worden aangeduid met de notatie [self.attribut];
- regels 23-24 laten zien dat het object [p] zowel een instantie is van de klasse [Personne] als van de klasse [object];
Resultaten
C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\venv\Scripts\python.exe C:/Data/st-2020/dev/python/cours-2020/python3-flask-2020/classes/01/classes_02.py
personne=[Paul,de la Hûche,48]
type(p)=<class '__main__.Personne'>
isinstance(Personne)=True, isinstance(object)=True
Process finished with exit code 0
12.3. Script [classes_03]: de klasse Personne met een constructor
Het script [classes_03] toont het normale gebruik van een klasse:
# klasse Persoon
class Personne:
# constructor – initialiseert drie attributen
def __init__(self: object, prénom: str, nom: str, âge: int):
# voornaam: voornaam van de persoon
# achternaam: achternaam van de persoon
# leeftijd: leeftijd van de persoon
self.prénom = prénom
self.nom = nom
self.âge = âge
# geeft de attributen van de klasse weer als een tekenreeks
def identité(self: object) -> str:
return f"[{self.prénom},{self.nom},{self.âge}]"
# ---------------------------------- hand
# een Person-object
p = Personne("Paul", "de la Hûche", 48)
# aanroep van een methode
print(f"personne={p.identité()}")
Opmerkingen:
- regel 4: de constructor van een klasse heet __init__. Net als bij de andere methoden is de eerste parameter self;
- regel 20: een object Personne wordt aangemaakt met de constructor van de klasse;
- regels 13-15: de methode [identité] retourneert een tekenreeks die de inhoud van het object weergeeft;
- regel 22: weergave van de identiteit van de persoon;
Resultaten
C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\venv\Scripts\python.exe C:/Data/st-2020/dev/python/cours-2020/python3-flask-2020/classes/01/classes_03.py
personne=[Paul,de la Hûche,48]
Process finished with exit code 0
12.4. Script [classes_04]: statische methoden
In de map [modules] definiëren we de volgende klasse [Utils] (utils.py):

class Utils:
# statische methode
@staticmethod
def is_string_ok(string: str) -> bool:
# is string een tekenreeks
erreur = not isinstance(string, str)
if not erreur:
# is de tekenreeks leeg?
erreur = string.strip() == ''
# resultaat
return not erreur
Opmerkingen
- regel 3: de annotatie [@staticmethod] geeft aan dat de aldus geannoteerde methode een klassemethode is en geen instantiemethode. Dit blijkt uit het feit dat de eerste parameter van de aldus geannoteerde methode niet het sleutelwoord [self] is. De statische methode heeft dus geen toegang tot de attributen van het object. In plaats van te schrijven:
schrijven we
Omdat we hierboven [Utils.is_string_ok] hebben geschreven, wordt de methode [is_string_ok] een klassemethode genoemd (in dit geval de klasse Utils). Daarom moet de methode [Utils.is_string_ok] worden geannoteerd met het trefwoord [@staticmethod].
Met de statische methode [Utils.is_string_ok] kan hier worden gecontroleerd of een gegeven een niet-lege tekenreeks is.
Het script [classes_04] gebruikt de klasse [Utils] op de volgende manier:
# de applicatie wordt geconfigureerd
import config
config = config.configure()
# het syspath is geconfigureerd – we kunnen de imports uitvoeren
from utilitaires import Utils
print(Utils.is_string_ok(" "))
print(Utils.is_string_ok(47))
print(Utils.is_string_ok(" q "))
- regels 1-4: er wordt een configuratiescript gebruikt;
Het configuratiescript [config.py] ziet er als volgt uit:
def configure():
import os
# map van het configuratiebestand
script_dir = os.path.dirname(os.path.abspath(__file__))
# absolute paden van de mappen die in het syspath moeten worden opgenomen
absolute_dependencies = [
f"{script_dir}/shared",
"C:/Data/st-2020/dev/python/cours-2020/python3-flask-2020/venv/lib/site-packages",
"C:/myprograms/Python38/lib",
"C:/myprograms/Python38/DLLs"
]
# syspath bijgewerkt
from myutils import set_syspath
set_syspath(absolute_dependencies)
# de configuratie wordt teruggestuurd
return {}
- regel 9: de map [shared] wordt in het Python Path geplaatst;
Het resultaat van de uitvoering is als volgt:
12.5. Script [classes_05]: validatiecontroles van attributen
Het script [classes_05] introduceert nieuwe begrippen:
- definitie van een eigen uitzonderingstype;
- definitie van de methode [_str_], de standaardidentiteitsmethode van de klassen;
- definitie van eigenschappen;
# de applicatie wordt geconfigureerd
import config
config = config.configure()
# de syspath is geconfigureerd – we kunnen de imports uitvoeren
from utilitaires import Utils
# een eigen uitzonderingsklasse die afgeleid is van [BaseException]
class MyException(BaseException):
# er gebeurt niets: lege klasse
pass
# klasse Personne
class Personne:
# constructor
def __init__(self: object, prénom: str = "x", nom: str = "y", âge: int = 0):
# voornaam: voornaam van de persoon
# achternaam: achternaam van de persoon
# leeftijd: leeftijd van de persoon
# opslag van de parameters
# de initialisaties worden uitgevoerd via de setters
self.prénom = prénom
self.nom = nom
self.âge = âge
# methode toString van de klasse
def __str__(self: object) -> str:
return f"[{self.__prénom},{self.__nom},{self.__âge}]"
# getters
@property
def prénom(self) -> str:
return self.__prénom
@property
def nom(self) -> str:
return self.__nom
@property
def âge(self) -> int:
return self.__âge
# setters
@prénom.setter
def prénom(self, prénom: str):
# de voornaam mag niet leeg zijn
if Utils.is_string_ok(prénom):
self.__prénom = prénom.strip()
else:
raise MyException("Le prénom doit être une chaîne de caractères non vide")
@nom.setter
def nom(self, nom: str):
# de voornaam mag niet leeg zijn
if Utils.is_string_ok(nom):
self.__nom = nom.strip()
else:
raise MyException("Le nom doit être une chaîne de caractères non vide")
@âge.setter
def âge(self, âge: int):
# de leeftijd moet een geheel getal zijn >=0
erreur = False
if isinstance(âge, int):
if âge >= 0:
self.__âge = âge
else:
erreur = True
else:
erreur = True
# fout?
if erreur:
raise MyException("L'âge doit être un entier >=0")
# ---------------------------------- main
# een Personne-object
try:
# instantie van de klasse Personne
p = Personne("Paul", "de la Hûche", 48)
# weergave van object p
print(f"personne={p}")
except MyException as erreur:
# fout weergeven
print(erreur)
# een ander Personne-object
try:
# instantie van de klasse Persoon
p = Personne("xx", "yy", "zz")
# weergave van object p
print(f"personne={p}")
except MyException as erreur:
# fout weergeven
print(erreur)
# een andere persoon, ditmaal zonder parameters
try:
# instantie van de klasse 'Persoon'
p = Personne()
# weergave van object p
print(f"personne={p}")
except MyException as erreur:
# foutmelding weergeven
print(erreur)
# toegang tot de privé-attributen __attr van de klasse is niet mogelijk
p.__prénom = "Gaëlle"
print(f"p.prénom={p.prénom}")
print(f"p.__prénom={p.__prénom}")
p.prénom = "Sébastien"
print(f"p.prénom={p.prénom}")
print(f"p.__prénom={p.__prénom}")
Opmerkingen:
- regels 10-13: een klasse MyException die is afgeleid van de klasse BaseException (we zullen hier later op terugkomen). Deze voegt geen functionaliteit toe aan de laatstgenoemde klasse. Ze is er alleen om een eigen uitzondering te hebben;
- regel 19: de constructor heeft standaardwaarden voor zijn parameters. Daardoor is de bewerking p=Personne() gelijk aan p=Personne("x","y",0);
- regels 34-45: de eigenschappen van de klasse. Dit zijn methoden die zijn geannoteerd met het trefwoord [@property]. Ze worden gebruikt om de waarde van de attributen weer te geven;
- regels 47-77: de setters van de klasse. Dit zijn methoden die zijn geannoteerd met het trefwoord [@attributsetter]. Ze worden gebruikt om de waarde van de attributen vast te leggen;
- regels 48-54: de setter van het attribuut [prénom]. Deze methode wordt aangeroepen telkens wanneer er een waarde wordt toegewezen aan het attribuut [prénom]:
Regel 2 zorgt ervoor dat [p.prénom(valeur)] wordt aangeroepen. Het voordeel van het gebruik van een setter om een waarde aan een attribuut toe te wijzen, is dat de setter een functie is, waardoor de geldigheid van de aan het attribuut toegewezen waarde kan worden gecontroleerd;
- regel 51: er wordt gecontroleerd of de waarde die aan het attribuut [prénom] wordt toegewezen een niet-lege tekenreeks is. Hiervoor wordt de eerder besproken statische methode [Utils.isStringOk] gebruikt;
- regel 52: de waarde die aan het attribuut [prénom] is toegewezen, wordt ontdaan van de „spaties” aan het begin en einde van de tekenreeks en toegewezen aan het attribuut [self.__prénom]. Het is dus niet het attribuut [prénom] dat hier wordt gebruikt. Dat kon niet, anders zouden we een oneindige recursieve aanroep hebben gehad. We hadden elke willekeurige attribuutnaam kunnen gebruiken. Het feit dat we het attribuut [__prénom] hebben gebruikt met twee onderstrepingstekens aan het begin van de identificatiecode heeft een speciale betekenis: attributen die worden voorafgegaan door twee onderstrepingstekens zijn privé voor de klasse. Dit betekent dat ze niet zichtbaar zijn van buitenaf. We kunnen dus niet schrijven:
In feite zullen we straks zien dat je dit wel kunt schrijven, maar dat het de voornaam niet wijzigt. Het doet iets anders;
- regels 53-54: als de waarde die aan de voornaam wordt toegewezen niet correct is, wordt er een uitzondering gegenereerd. Zo weet de aanroepende code dat de aanroep onjuist is;
- regels 35-37: de eigenschap [prénom]. Deze wordt elke keer aangeroepen wanneer [p.prénom] in een uitdrukking wordt geschreven. Dan wordt de methode [p.prénom()] aangeroepen. Op regel 37 wordt de waarde van het attribuut [__prénom] teruggegeven, aangezien we hebben gezien dat de setter van het attribuut [prénom] de waarde ervan toewijst aan het privé-attribuut [__prénom];
- regels 56-62: de setter van het attribuut [nom] is op dezelfde manier opgebouwd als die van het attribuut [prénom]. Hetzelfde geldt voor die van het attribuut [âge] in de regels 64-77;
- hoewel de eigenschappen [prénom, nom, valeur] niet de eigenlijke attributen zijn – die zijn in werkelijkheid [__prénom, __nom, __âge] – zullen we ze toch de attributen van de klasse blijven noemen, omdat ze als zodanig worden gebruikt;
- regels 19-28: de constructor van de klasse maakt impliciet gebruik van de setters van de attributen [prénom, nom, âge]. Als er namelijk in regel 26 [self.prénom = prénom] wordt geschreven, wordt impliciet de methode [prénom(self, prénom)] aangeroepen. De geldigheid van de parameter [prénom] wordt dan gecontroleerd. Hetzelfde geldt voor de twee andere attributen [nom, âge];
- met dit model kunnen er geen onjuiste waarden worden toegekend aan de attributen [prénom, nom, âge] van de klasse;
- regels 30-32: de functie __str__ vervangt de methode die voorheen identité heette. De naam [__str__] (met twee onderstrepingstekens voor en achter) is niet toevallig. Dat zullen we later zien;
- regels 83-86: instantiëren van een persoon en vervolgens weergeven van diens identiteit;
- regel 84: instantiëren;
- regel 86: weergave. De bewerking vraagt om de persoon p weer te geven in de vorm van een tekenreeks. De Python-interpreter roept dan automatisch de methode p.__str__() aan, indien deze bestaat. Deze methode vervult dezelfde rol als de methode toString() in Java of in de talen .NET;
- regels 87-89: afhandeling van een eventuele uitzondering van het type MyException. Geeft vervolgens de fout weer;
- regels 91-99: idem voor een tweede persoon die met onjuiste parameters is geïnstantieerd;
- regels 102-109: idem voor een derde persoon die wordt geïnstantieerd met de standaardparameters: er worden geen parameters doorgegeven. Hier worden dus de standaardwaarden van deze parameters in de constructor gebruikt;
- regels 112-117: we hebben gezegd dat het attribuut [__prénom] privé is en dus normaal gesproken niet toegankelijk is van buiten de klasse. We willen dit controleren;
- regels 112-114: er wordt een waarde toegewezen aan het attribuut [__prénom], waarna de waarde van de attributen [__prénom] en [prénom] wordt gecontroleerd, die normaal gesproken hetzelfde zijn;
- regels 115-117: de bewerking wordt herhaald, waarbij ditmaal het attribuut [prénom] wordt geïnitialiseerd;
Resultaten
C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\venv\Scripts\python.exe C:/Data/st-2020/dev/python/cours-2020/python3-flask-2020/classes/01/classes_05.py
personne=[Paul,de la Hûche,48]
L'âge doit être un entier >=0
personne=[x,y,0]
p.prénom=x
p.__prénom=Gaëlle
p.prénom=Sébastien
p.__prénom=Gaëlle
Process finished with exit code 0
Opmerkingen
- regels 5-6: we zien dat de toewijzing [p.__prénom = "Gaëlle"] de waarde van het attribuut [prénom], regel 5, niet heeft gewijzigd;
- regels 7-8: we zien dat de toewijzing [p.prénom = "Sébastien"] de waarde van het attribuut [__prénom] niet heeft gewijzigd, regel 8;
Wat kunnen we hieruit afleiden? Waarschijnlijk heeft de bewerking [p.__prénom = "Gaëlle"] een openbaar attribuut [__prénom] aan de klasse toegevoegd, maar dat dit verschilt van het privé-attribuut [__prénom] dat binnen de klasse wordt bewerkt;
12.6. Script [classes_06]: toevoeging van een methode voor het initialiseren van het object
Het script [classes_06] voegt een methode toe aan de klasse [Personne]:
# de applicatie wordt geconfigureerd
import config
config = config.configure()
# het syspath is geconfigureerd – de imports kunnen worden uitgevoerd
from utilitaires import Utils
# een eigen uitzonderingsklasse die is afgeleid van [BaseException]
class MyException(BaseException):
# er gebeurt niets: lege klasse
pass
# klasse Persoon
class Personne:
# constructor
def __init__(self: object, prénom: str = "x", nom: str = "y", âge: int = 0):
# voornaam: voornaam van de persoon
# achternaam: achternaam van de persoon
# leeftijd: leeftijd van de persoon
# opslag van de parameters
# de initialisaties worden uitgevoerd via de setters
self.prénom = prénom
self.nom = nom
self.âge = âge
# andere initialisatiemethode
def init_with_personne(self: object, p: object):
# initialiseert het huidige object met een persoon p
self.__init__(p.prénom, p.nom, p.âge)
# methode toString van de klasse
def __str__(self: object) -> str:
return f"[{self.__prénom},{self.__nom},{self.__âge}]"
# getters
…
# setters
…
# ---------------------------------- main
# een Personne-object
try:
# instantiëren van de klasse Personne
p = Personne("Paul", "de la Hûche", 48)
# weergave van object p
print(f"personne={p}")
except MyException as erreur:
# weergave van foutmelding
print(erreur)
# een ander Personne-object
try:
# instantie van de klasse Persoon
p = Personne("xx", "yy", "zz")
# weergave van object p
print(f"p={p}")
except MyException as erreur:
# foutmelding weergeven
print(erreur)
# een andere persoon, ditmaal zonder parameters
try:
# instantie van de klasse Personne
p = Personne()
# weergave van object p
print(f"p={p}")
except MyException as erreur:
# foutmelding weergeven
print(erreur)
# een andere Personne verkregen door kopiëren
try:
# instantie van de klasse Personne
p2 = Personne()
p2.init_with_personne(p)
# weergave van object p2
print(f"p2={p2}")
except MyException as erreur:
# foutmelding weergeven
print(erreur)
Opmerkingen:
- het verschil met het vorige script zit in de regels 30-33. De methode initWithPersonne is toegevoegd. Deze maakt gebruik van de constructor __init__. Het is niet mogelijk om, zoals in getypeerde talen, methoden met dezelfde naam te hebben die worden onderscheiden door de aard van hun parameters of hun resultaat. Het is dus niet mogelijk om meerdere constructors te hebben die het object op basis van verschillende parameters zouden construeren, in dit geval een object van het type Personne;
Resultaten
C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\venv\Scripts\python.exe C:/Data/st-2020/dev/python/cours-2020/python3-flask-2020/classes/01/classes_06.py
personne=[Paul,de la Hûche,48]
L'âge doit être un entier >=0
p=[x,y,0]
p2=[x,y,0]
Process finished with exit code 0
12.7. Script [classes_07]: een lijst met Personne-objecten
We plaatsen de klassen [MyException] en [Personne] nu in een module, zodat we ze kunnen gebruiken zonder hun code te hoeven kopiëren:

Beide klassen bevinden zich in de bovenstaande module [myclasses.py].
Het script [classes_07] laat zien dat we een lijst met objecten kunnen maken:
# de applicatie wordt geconfigureerd
import config
config = config.configure()
# het syspath is geconfigureerd – we kunnen de imports uitvoeren
from myclasses import Personne
# ---------------------------------- main
# een lijst met personen aanmaken
groupe = [Personne("Paul", "Langevin", 48), Personne("Sylvie", "Lefur", 70)]
# identiteit van deze personen
for i in range(len(groupe)):
print(f"groupe[{i}]={groupe[i]}")
Opmerkingen:
- regel 7: we importeren de klasse [Personne];
- regel 11: een lijst met objecten van het type [Personne];
- regels 13-14: we doorlopen deze lijst om elk van de elementen weer te geven;
- regel 14: de functie [print] geeft de tekenreeks weer die het object [groupe[i]] vertegenwoordigt. Standaard wordt hiervoor de methode [__str__] aangeroepen;
Resultaten
C:\Users\serge\.virtualenvs\cours-python-v02\Scripts\python.exe C:/Data/st-2020/dev/python/cours-2020/v-02/classes/01/classes_07.py
groupe[0]=[Paul,Langevin,48]
groupe[1]=[Sylvie,Lefur,70]
Process finished with exit code 0
12.8. Script [classes_08]: aanmaken van een klasse die is afgeleid van de klasse Personne
In de module [myclasses] definiëren we de volgende klasse [Enseignant]:
# klasse Docent
class Enseignant(Personne):
# oprichter
def __init__(self, prénom: str = "x", nom: str = "x", âge: int = 0, discipline: str = "x"):
# voornaam: voornaam van de persoon
# achternaam: achternaam van de persoon
# leeftijd: leeftijd van de persoon
# vak: vak dat wordt onderwezen
# initialen van de ouder
Personne.__init__(self, prénom, nom, âge)
# overige initialen
self.discipline = discipline
# toString
def __str__(self) -> str:
return f"enseignant[{super().__str__()},{self.discipline}]"
# eigenschappen
@property
def discipline(self) -> str:
return self.__discipline
@discipline.setter
def discipline(self, discipline: str):
# de discipline moet een niet-lege tekenreeks zijn
if Utils.is_string_ok(discipline):
self.__discipline = discipline
else:
raise MyException("La discipline doit être une chaîne de caractères non vide")
- regel 2: verklaart de klasse Enseignant tot een afgeleide klasse van de klasse Personne. Een afgeleide klasse heeft alle eigenschappen (attributen en methoden) van haar bovenliggende klasse plus haar eigen eigenschappen;
- regel 13: de klasse [Enseignant] definieert een nieuw attribuut [discipline];
- regel 11: de constructor van de afgeleide klasse Enseignant moet de constructor van de bovenliggende klasse Personne aanroepen en daarbij de verwachte parameters doorgeven;
- regel 17: de functie [super()] retourneert de bovenliggende klasse. Hier wordt de functie [__str__] van de bovenliggende klasse aangeroepen;
- regels 19-30: de getter en setter van het nieuwe attribuut [discipline] worden gedefinieerd;
Het script [classes_08] gebruikt de klasse [Enseignant] als volgt:
# de applicatie wordt geconfigureerd
import config
config = config.configure()
# het syspath is geconfigureerd – we kunnen de imports uitvoeren
from myclasses import Personne, Enseignant
# ---------------------------------- main
# aanmaken van een array met Person-objecten en afgeleide objecten
groupe = [Enseignant("Paul", "Langevin", 48, "anglais"), Personne("Sylvie", "Lefur", 70)]
# identiteit van deze personen
for i in range(len(groupe)):
print(f"groupe[{i}]={groupe[i]}")
Opmerkingen:
- regel 7: de klassen [Personne] en [Enseignant], gedefinieerd in het bestand [myclasses.py], worden geïmporteerd;
- regels 11-14: er wordt een groep personen gedefinieerd waarvan vervolgens de identiteit wordt weergegeven;
Resultaten
C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\venv\Scripts\python.exe C:/Data/st-2020/dev/python/cours-2020/python3-flask-2020/classes/01/classes_08.py
groupe[0]=enseignant[[Paul,Langevin,48],anglais]
groupe[1]=[Sylvie,Lefur,70]
Process finished with exit code 0
12.9. Script [classes_09]: tweede klasse afgeleid van de klasse Persoon
Het script [classes_09] introduceert de klasse [Etudiant], afgeleid van de klasse [Personne]. Deze is als volgt gedefinieerd in de module [myclasses]:
# klasse Student
class Etudiant(Personne):
# constructor
def __init__(self: object, prénom: str = "x", nom: str = "y", âge: int = 0, formation: str = "x"):
Personne.__init__(self, prénom, nom, âge)
self.formation = formation
# toString
def __str__(self: object) -> str:
return f"étudiant[{super().__str__()},{self.formation}]"
# eigenschappen
@property
def formation(self) -> str:
return self.__formation
@formation.setter
def formation(self, formation: str):
# de opleiding moet een niet-lege tekenreeks zijn
if Utils.is_string_ok(formation):
self.__formation = formation
else:
raise MyException("La formation doit être une chaîne de caractères non vide")
Het script [classes_09] gebruikt de klasse [Etudiant] als volgt:
# de applicatie wordt geconfigureerd
import config
config = config.configure()
# het syspath is geconfigureerd – we kunnen de imports uitvoeren
from myclasses import Personne, Enseignant, Etudiant
# ---------------------------------- main
# aanmaken van een array met Person-objecten en afgeleide objecten
groupe = [Enseignant("Paul", "Langevin", 48, "anglais"), Personne("Sylvie", "Lefur", 70),
Etudiant("Steve", "Boer", 22, "iup2 qualité")]
# identiteit van deze personen
for personne in groupe:
# weergave van een persoon
print(personne)
Opmerkingen:
- dit script is vergelijkbaar met het vorige.
Resultaten
C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\venv\Scripts\python.exe C:/Data/st-2020/dev/python/cours-2020/python3-flask-2020/classes/01/classes_09.py
enseignant[[Paul,Langevin,48],anglais]
[Sylvie,Lefur,70]
étudiant[[Steve,Boer,22],iup2 qualité]
Process finished with exit code 0
12.10. Script [classes_10]: de eigenschap [__dict__]
Het script [classes_10] bevat de eigenschap [__dict__] die we hierna vaak zullen gebruiken:
# de applicatie wordt geconfigureerd
import config
config = config.configure()
# het syspath is geconfigureerd – de imports kunnen worden uitgevoerd
from myclasses import Etudiant
# ---------------------------------- main
# een student aanmaken
étudiant=Etudiant("Steve", "Boer", 22, "iup2 qualité")
# eigenschappenwoordenboek
print(étudiant.__dict__)
Opmerkingen
- regels 1-4: de toepassing wordt geconfigureerd;
- regel 7: de klasse [Etudiant] wordt geïmporteerd;
- regel 11: instantiëren van een student;
- regel 13: gebruik van de vooraf gedefinieerde methode [__dict__] (2 onderstreepte tekens voor en na de ID);
De resultaten zijn als volgt:
- regel 2: we krijgen een woordenboek waarvan de sleutels de eigenschappen van het object zijn, voorafgegaan door de naam van de klasse waartoe ze behoren. We zullen dit woordenboek gebruiken om een brug te slaan tussen het object en het woordenboek;