ID.nl logo
Zo kun je programmeren in Python - Deel 7
© PXimport
Huis

Zo kun je programmeren in Python - Deel 7

In de href="https://computertotaal.nl/artikelen/how-to/zo-kun-je-programmeren-in-python-deel-6/" rel="noopener noreferrer" target="_blank">vorige les</a> leerde je hoe je met functies en modules wat meer structuur brengt in je Python-programma’s. Maar structuur gaat niet alleen over wat je doet, maar ook over welke data je verwerkt. In deze les leren we daarom hoe je data structureert door je eigen datatypes te maken: klassen.

Tot nu toe bestaan onze Python-programma’s uit heel wat regels code die de standaard datatypes van Python verwerken. Maar als je programma wat complexer wordt, verwerk je misschien data met een speciale structuur en bijbehorende functionaliteit. Dan wordt het tijd om een klasse te definiëren, waarmee je een nieuw datatype creëert. Daarna kun je objecten van deze klasse aanmaken en die verwerken zoals je met objecten van de standaardklassen van Python werkt.

Begin bij les 1.

Een klasse definiëren

Stel dat we een programma schrijven waarin we berekeningen op punten in een tweedimensionaal vlak willen uitvoeren. We maken dan de volgende klasse:

import math

class Point:

def __init__(self, x=0, y=0):
self.x = x
self.y = y

def __repr__(self):
return 'Point({}, {})'.format(self.x, self.y)

def displacement(self, other_point):
return Point(other_point.x - self.x, other_point.y - self.y)

def distance(self, other_point):
relative_position = self.displacement(other_point)
return math.sqrt(relative_position.x**2 + relative_position.y**2)

In het begin importeren we de module math omdat we de functie sqrt nodig hebben om de vierkantswortel uit te rekenen. Daarna definiëren we een klasse Point met class Point:. Alles wat zich in dat blok bevindt, maakt onderdeel uit van de klasse.

Objecten aanmaken

Negeer even wat er allemaal in de definitie van de klasse staat, sla bovenstaande code op in het bestand point.py en voer het uit in Thonny. In de terminal kun je nu objecten van het type Point aanmaken en er berekeningen mee uitvoeren:

>>> p = Point()
>>> p
Point(0, 0)
>>> p1 = Point(5, 7)

>>> p2 = Point(2, 1)
>>> p1.distance(p2)
6.708203932499369

>>> p2.x = 0

>>> p2

Point(0, 1)

>>> p1.distance(p2)

7.810249675906654

Methodes en objectvariabelen

Dan is het nu tijd om in de definitie van de klasse te duiken. We zien in de klasse vier functies, maar in een klasse noemen we ze methodes. Een methode is dus een functie die aan een klasse is gekoppeld. Een opvallend verschil tussen een functie buiten een klasse en een methode is dat de eerste parameter van een methode altijd self is: dat is een variabele die verwijst naar het object zelf waarop je de methode aanroept.

Een object kan ook variabelen hebben (objectvariabelen of instance variables in het Engels). In onze klasse zijn dat self.x en self.y. De methode __init__ heeft een speciale betekenis: hiermee initialiseer je het object. Meestal geef je in deze methode de objectvariabelen een waarde. Omdat een punt x- en y-coördinaten heeft, bestaat onze initialisatie uit self.x = x en self.y = y: we initialiseren beide objectvariabelen met de waarden die je als argument aan __init__ doorgeeft. Als je dus een object p1 aanmaakt met p1 = Point(5, 7), krijgt de objectvariabele self.x van p1 de waarde 5 en self.y de waarde 7.

Overigens gebruiken we in de definitie van __init__ iets wat je voor alle functies kunt doen: standaardwaarden instellen. Met x=0 en y=0 in de lijst met parameters geven we aan dat x en y de waarde 0 krijgen als je bij het initialiseren van een Point geen argumenten doorgeeft. Daarom heeft p = Point() de coördinaten (0, 0), wat je kunt controleren door p.x en p.y op te vragen, of zoals we in ons voorbeeld deden door gewoon p in de terminal in te voeren.

Dit laatste werkt omdat we de speciale methode __repr__ hebben gedefinieerd. Als je die functie voor een klasse definieert, moet je daarin een string teruggeven die het object voorstelt alsof je het in Python-code aanmaakt. Als we deze functie niet hadden gedefinieerd, kregen we in de terminal iets te zien als <__main__.Point object at 0x7f27e24ad940>, wat je alleen leert dat het om een Point-object gaat, en niets meer.

In de methode distance berekenen we de afstand tussen het punt zelf en een ander punt met behulp van de stelling van Pythagoras. Daarvoor berekenen we eerst de relatieve positie van het andere punt ten opzichte van het punt zelf. Dat doen we door een andere methode van het punt aan te roepen: displacement. Omdat ook deze methode tot het object zelf behoort, roep je dit aan als: self.displacement. Merk op dat we in de methode displacement een Point-object teruggeven. Dat mag gewoon!

De klasse veralgemenen

Door met klassen te werken, wordt je code heel wat gestructureerder en leesbaarder, maar na een tijdje zul je merken dat sommige klassen speciale gevallen zijn van andere klassen. Zo bestaan er tweedimensionale punten, driedimensionale en n-dimensionale. Kunnen we geen klasse maken die het algemene n-dimensionale geval afhandelt en dan specifieke klassen voor twee- en driedimensionale punten zonder alle methodes meerdere keren te moeten definiëren? Ja dat kan in Python, met iets wat we overerving van klassen noemen.

Laten we eerst onze klasse Point veralgemenen tot het n-dimensionale geval:

import math

class Point:

def __init__(self, *coordinates):
self.coordinates = list(coordinates)

def __repr__(self):
return 'Point(' + ', '.join([str(co) for co in self.coordinates]) + ')'

def displacement(self, other_point):
return Point(*[a-b for a, b in zip(other_point.coordinates, self.coordinates)])
def distance(self, other_point):

relative_position = self.displacement(other_point)
return math.sqrt(sum([i**2 for i in relative_position.coordinates]))

Zoals je ziet, lijkt die heel erg op het tweedimensionale geval. Een subtiel verschil is dat we de coördinaten aan __init__ niet meer als x en y kunnen opgeven, maar een willekeurig aantal argumenten doorgeven. Dat geven we aan met de asterisk (*) voor de parameter coordinates. Dat willekeurig aantal argumenten zetten we dan om naar een lijst en kennen we dan toe aan de objectvariabele coordinates.

In de methode __repr__ gebruiken we list comprehension (zie deel 4 van de cursus) om alle afzonderlijke coördinaten uit de lijst coordinates te halen en die naar een string om te zetten. Dat is nodig omdat we al die strings daarna met de functie join aan elkaar plakken, met een komma ertussen.

Zip

Ook in de twee andere methodes maken we gebruik van list comprehension om door alle coördinaten te gaan. De lastigste methode om te begrijpen is displacement. We willen daar van de twee punten telkens de overeenkomende coördinaten van elkaar aftrekken en van het resultaat een Point-object maken. Met de functie zip maken we een lijst van tupels van de overeenkomende coördinaten. Met een list comprehension maken we dan een lijst met het verschil van de twee elementen van het tupel voor alle tupels in die lijst. En uiteindelijk zetten we die lijst met * om naar een willekeurig aantal argumenten dat we aan Point doorgeven.

Als dit allemaal wat abstract lijkt, probeer dit dan eens uit met twee korte lijsten coördinaten, zoals [1, 4, 2] en [3, 4, 1]:

>>> c1 = [1, 4, 2]
>>> c2 = [3, 4, 1]

>>> koppels = zip(c1, c2)
>>> list(koppels)

[(1, 3), (4, 4), (2, 1)]
>>> [a-b for a, b in koppels]
[-2, 0, 1]

Overerving

We hebben nu een heel algemene klasse Point waarmee we punten in alle mogelijke dimensies kunnen voorstellen en er berekeningen op kunnen uitvoeren. Maar in de meeste toepassingen hebben we slechts twee of drie dimensies nodig en dan willen we weer naar de coördinaten met x en y kunnen verwijzen zoals in de eerste klasse in deze cursus. Hoe maken we nu klassen Point2D en Point3D zonder de algemene code van Point te herhalen? Dat doen we door deze klassen te laten overerven van Point. Point noemen we dan de superklasse en de klassen die ervan overerven zijn de subklassen. We zouden dat als volgt kunnen doen:

class Point2D(Point):

def __init__(self, x=0, y=0):
self.x = x

self.y = y
Point.__init__(self, x, y)

class Point3D(Point):

def __init__(self, x=0, y=0, z=0):
self.x = x
self.y = y
self.z = z
Point.__init__(self, x, y, z)

We zien hier hoe we de klasse Point2D definiëren, met tussen haakjes de superklasse, Point. Daarna definiëren we de methode __init__ zoals we dat in het begin van deze les deden, met als enige verschil dat we op het einde van de methode met Point.__init__(self, x, y) de methode __init__ van de superklasse aanroepen met als argumenten de x- en y-coördinaten. Zo zorgen we dat de superklasse zijn lijst met coördinaten correct initialiseert.

Je kunt nu Point2D-objecten maken en er de methodes displacement en distance op uitvoeren, zonder dat we die in de klasse Point2D hebben gedefinieerd. Point2D erft immers alle methodes en objectvariabelen van zijn superklasse over:

>>> p = Point2D(1, 2)
>>> p
Point(1, 2)
>>> p.coordinates

[1, 2]

>>> p.x

1
>>> p2 = Point2D(3, 5)
>>> p.distance(p2)
3.605551275463989

Als we dus een Point2D-object aanmaken, wordt de methode __init__ van Point2D aangeroepen, omdat we die in Point2D hebben gedefinieerd. Op het einde van die methode roepen we de methode van de superklasse aan. Als we de objectvariabelen x of y gebruiken, worden die variabelen van Point2D gebruikt, omdat we ze in die subklasse hebben gedefinieerd. Maar als we naar de objectvariabele coordinates verwijzen of de methodes __repr__, displacement of distance aanroepen, worden de versies in de klasse Point gebruikt omdat we die niet in Point2D hebben gedefinieerd. Op deze manier is overerving een handig hulpmiddel om herhaling in je code te vermijden.

Samenvatting

In deze les heb je geleerd hoe je zelf datatypes definieert door klassen aan te maken met methodes en objectvariabelen. Je hebt ook wat abstract leren denken bij het programmeren: hoe veralgemeen je code, bijvoorbeeld om op een willekeurig aantal coördinaten en met een willekeurig aantal argumenten voor een functie te werken? Die abstractie hebben we ook doorgetrokken door met superklassen en subklassen te werken, zodat je vermijdt dat je code moet herhalen als je klassen definieert die op elkaar lijken. Je hebt ook eigenschappen leren definiëren. De complexiteit van je Python-programma’s wordt ondertussen al hoog genoeg om even een stapje terug te zetten. In de volgende les leer je je code te documenteren, te debuggen en te testen. Ook leer je meer over Python uit te zoeken door de helpfunctie te gebruiken.

Opdracht

Onze code is een verdienstelijke eerste poging, maar hij klopt nog niet. Als je immers p.x verandert, blijft p.coordinates zijn originele waarde behouden: *>>> p = Point2D(1, 2)

p Point(1, 2) p.coordinates [1, 2] p.x = 3 p.x 3 p Point(1, 2) p.coordinates [1, 2]* Maak de methodes get_x en set_x voor de klasse Point2D die de eerste coördinaat van de superklasse teruggeven dan wel de eerste coördinaat instellen. Met de Python-opdracht x = property(get_x, set_x) stel je x als eigenschap in, zodat je methodes get_x en set_x worden opgeroepen als je p.x opvraagt of een waarde geeft. Daarmee kun je ons probleem oplossen. Doe hetzelfde voor y en bij Point3D ook voor z.

Uitwerking

class Point2D(Point): def __init__(self, x=0, y=0): Point.__init__(self, x, y) self.x = x self.y = y

def get_x(self): return self.coordinates[0] def set_x(self, x): self.coordinates[0] = x x = property(get_x, set_x)

def get_y(self): return self.coordinates[1] def set_y(self, y): self.coordinates[1] = y y = property(get_y, set_y) Belangrijk is hier dat je in __init__ eerst __init__ van de superklasse oproept voordat je self.x = x zet. Die laatste roept immers set_x aan, die verwijst naar self.coordinates[0], wat pas door de initialisatie van de superklasse gedefinieerd is.

Cheatsheet

Attribuut: een eigenschap (methode of objectvariabele) van een klasse. Klasse: een datatype. Methode: een functie die aan een klasse gekoppeld is. Object: een concreet voorbeeld van een klasse. Objectvariabele: een variabele die aan een object gekoppeld is. Overerving: een klasse die een speciaal geval van een andere klasse is. Subklasse: een klasse die van een andere klasse overerft. Superklasse: een klasse waarvan een andere klasse overerft.

▼ Volgende artikel
😱 Het Blue Screen of Death van Windows gaat voorgoed verdwijnen
© Valeriia Lukashova
Huis

😱 Het Blue Screen of Death van Windows gaat voorgoed verdwijnen

Iedereen die met Windows werkt, kent het wel: ineens een blauw scherm, en dan… niets meer. Het beruchte Blue Screen of Death (BSOD) hoort al sinds de jaren 90 bij Windows als pindakaas bij brood. Maar daar komt nu verandering in: het blauwe scherm gaat verdwijnen.

Het Blue Screen of Death bestaat al sinds de jaren 90. In Windows NT verscheen het voor het eerst in zijn bekende vorm: witte foutcodes op een felblauw vlak. De melding verscheen bij serieuze systeemfouten, vaak veroorzaakt door een kapotte driver of instabiele hardware. In latere versies kwamen er ook een verdrietige emoticon :( bij en, sinds 2016, een QR-code die naar een informatiepagina leidde. Hoewel er weinig dingen zo frustrerend zijn als een BSOD, is-ie ook handig: de foutmelding en STOP-code* die erop staan, kunnen je namelijk helpen om te achterhalen wat er precies aan de hand is. Maar nu gaat het dus verdwijnen …
*Scrol naar beneden voor een overzicht met de meest voorkomende foutmeldingen/STOP-codes en hun betekenis.

©PXimport | Reshift Digital BV

Op zwart

Het is gelukkig iets minder dramatisch dan je denkt: Microsoft gaat het blauwe scherm vervangen door een zwarte variant. Het nieuwe ontwerp oogt rustiger, zonder QR-code of icoontjes, en toont direct de foutcode en de driver die mogelijk de oorzaak is. Handig voor wie het probleem wil opzoeken of oplossen.

De nieuwe interface is vanaf later deze zomer beschikbaar op alle computers die draaien op Windows 11 versie 24H2. Naast het zwarte scherm wordt ook het meldingsscherm dat je ziet bij onverwachte herstarts vernieuwd. Dat sluit beter aan op de rest van Windows 11, is overzichtelijker en verdwijnt vaak al binnen een paar seconden.

©Microsoft

Waarom deze verandering?

Volgens Microsoft draait het om duidelijkheid. Het scherm moet beter laten zien of het probleem in Windows zelf zit, of in een externe component. Dat scheelt tijd bij het zoeken naar de oorzaak. Zeker na de wereldwijde CrowdStrike-storing van vorig jaar – waarbij miljoenen computers vastliepen door een fout in beveiligingssoftware – wil Microsoft de foutafhandeling beter en sneller maken.

Quick Machine Recovery

Naast het nieuwe scherm introduceert Microsoft ook Quick Machine Recovery (QMR). Deze functie is bedoeld voor situaties waarin een pc helemaal niet meer opstart. Via de herstelomgeving van Windows kan het systeem dan automatisch reparaties uitvoeren, zonder dat je handmatig iets hoeft te doen of een expert hoeft in te schakelen.

QMR wordt later dit jaar beschikbaar op alle apparaten met Windows 11 versie 24H2. Op Home-edities staat het standaard aan. De functie wordt op dit moment al getest in het Beta Channel van het Windows Insider-programma, zodat Microsoft nog kan bijschaven waar nodig.

Wat merk jij ervan?

Voor de meeste mensen betekent dit vooral dat de foutmelding bij een crash er straks anders uitziet. Maar het belangrijkste verschil zit onder de motorkap: Windows toont duidelijker wat er misgaat en kan zichzelf sneller herstellen. In de volksmond zal er – denken wij – overigens weinig veranderen: Blue of Black, het zal een BSOD blijven.

Foutmeldingen en STOP-codes

PAGE_FAULT_IN_NONPAGED_AREA STOP-code: 0x00000050 Windows probeert een deel van het geheugen te gebruiken dat niet beschikbaar is. Dit kan komen door kapot RAM-geheugen of problemen met de harde schijf.

IRQL_NOT_LESS_OR_EQUAL STOP-code: 0x0000000A Een onderdeel van Windows probeerde iets te doen op een moment dat dat niet mocht. Meestal komt dit door foutieve drivers of hardwareproblemen.

SYSTEM_SERVICE_EXCEPTION STOP-code: 0x0000003B Een onderdeel van Windows veroorzaakt een fout tijdens een systeemtaak. Vaak door oude of conflicterende software of drivers.

DRIVER_IRQL_NOT_LESS_OR_EQUAL STOP-code: 0x000000D1 Een driver probeert iets te doen met geheugen op het verkeerde moment. Dit wordt vaak veroorzaakt door slechte of onjuiste drivers.

INACCESSIBLE_BOOT_DEVICE STOP-code: 0x0000007B Windows kan bij het opstarten de schijf met systeembestanden niet bereiken. Oorzaak kan liggen in beschadigde bestanden of instellingen in het BIOS.

BAD_POOL_HEADER STOP-code: 0x00000019 Windows krijgt een fout in het geheugenbeheer. Dit kan komen door een slechte driver, hardwareproblemen of software die in de war raakt.

SYSTEM_THREAD_EXCEPTION_NOT_HANDLED STOP-code: 0x0000007E Windows krijgt een fout in een systeemonderdeel. De boosdoener is meestal een verouderde of kapotte driver.

WHEA_UNCORRECTABLE_ERROR STOP-code: 0x00000124 Windows ontdekt een ernstige hardwarefout of probleem met stroom of temperatuur. Ook defecte systeembestanden kunnen dit veroorzaken.

UNMOUNTABLE_BOOT_VOLUME STOP-code: 0x000000ED Windows kan de opstartschijf niet goed lezen. Dit gebeurt meestal tijdens het opstarten van de computer.

▼ Volgende artikel
Googles AI leest straks mee in WhatsApp – zo houd je de controle!
© gguy - stock.adobe.com
Huis

Googles AI leest straks mee in WhatsApp – zo houd je de controle!

Vanaf 7 juli krijgt Google Gemini toegang tot apps als WhatsApp, Telefoon en Berichten – zelfs als je dat niet expliciet hebt aangezet. Wat betekent dat voor je privacy? En hoe voorkom je dat de AI méér weet dan jij wilt? Dit moet je weten voordat de verandering ingaat.

In dit artikel lees je:
  • Wat Gemini straks kan doen met apps als WhatsApp en Berichten
  • Waarom Google deze wijziging doorvoert
  • Hoe dit je privacy beïnvloedt (zelfs als je tracking hebt uitgeschakeld)
  • Hoe je zelf de toegang van Gemini kunt beperken
  • Wat deze stap zegt over de toekomst van AI op je telefoon

Googles AI-assistent Gemini wordt komende maand verweven met een aantal nogal essentiële apps op je Android-toestel. Denk aan Telefoon, Berichten en zelfs WhatsApp. Dat blijkt uit een e-mail die Google eind juni verstuurde naar gebruikers van Gemini, meldt de website Android Authority. De toon van die boodschap riep meteen vragen op: helpt Gemini je straks óók als je tracking hebt uitgeschakeld? En wat betekent dat voor je privacy?

Ook interessant: Bezorgd over je privacy? Zo zet je Meta AI uit in je WhatsApp-chats

Nieuwe Android-smartphone nodig?

Bekijk hier de allernieuwste modellen!

Vage communicatie zorgt voor onrust

In de e-mail staat dat Gemini binnenkort ondersteuning biedt bij basisfuncties zoals bellen en berichten versturen, óók als je de zogeheten Gemini Apps Activity uit hebt staan. Op papier klinkt dat als een handige extra, maar in de praktijk leidde het vooral tot verwarring. Want als Gemini kan helpen zonder dat die activiteit is ingeschakeld, betekent dat dan dat de AI toch nog steeds meeleest of gegevens opslaat?

De formulering was vaag, de impact onduidelijk, en aangezien onze privacy in combinatie met AI sowieso al een heet hangijzer is, ging het nieuws als een lopend vuurtje door de techcommunity. Al snel verschenen er bezorgde reacties op sociale media en in forums, waarin gebruikers zich afvroegen of ze straks ongemerkt data afstaan aan een AI-systeem dat ze zelf niet actief gebruiken.

©Andrea

Google stelt gerust, maar nuanceert niet alles

Gelukkig kwam Google snel met verduidelijking. De kernboodschap: al biedt Gemini straks hulp bij je apps, dat betekent níét dat je persoonlijke gegevens automatisch worden verzameld of opgeslagen. Als je Gemini Apps Activity uit hebt staan, worden je gesprekken niet opgeslagen, niet gebruikt om modellen te trainen en verdwijnen ze na korte tijd automatisch. De AI gebruikt die tijdelijke gegevens alleen om je direct te kunnen helpen, bijvoorbeeld als je zegt 'bel mama' of 'stuur een bericht naar Daan'.

Toch blijft er een nuance hangen. De toegang van Gemini tot deze apps wordt standaard ingeschakeld voor iedereen, tenzij je dat zelf dus actief uitschakelt. Dat betekent dat de AI wel degelijk macht krijgt over je telefoonfuncties, tenzij jij ingrijpt. En hoewel de data niet worden opgeslagen, is er technisch gezien wel sprake van toegang tot privé-interactie, al is het kortstondig en geanonimiseerd.

Ook interessant: Spraakberichten in WhatsApp lezen, zo werkt het

Gebruikers kunnen zelf de stekker eruit trekken

Voor wie zich niet prettig voelt bij deze mate van AI-integratie, is er goed nieuws: je kunt de toegang van Gemini tot je apps volledig intrekken. Dat doe je via de instellingen van de Gemini-app binnen Android of via de speciale webpagina gemini.google.com/apps. Daar bepaal je per app of je Gemini toestemming geeft om ermee te werken. Zet je die toegang uit, dan stopt de AI simpelweg met bellen, berichten sturen of andere app-interacties. Je behoudt dus altijd de controle – als je tenminste weet waar je moet kijken.

Wat belangrijk is om te onthouden: deze wijziging betekent niet dat Gemini een spion wordt op je telefoon. Het is eerder een uitbreiding van de Assistent-functie, zoals we die kennen van eerdere AI-integraties binnen Android. Maar doordat AI steeds meer verweven raakt met je dagelijkse digitale handelingen, is het goed om scherp te blijven op wat wel en niet wordt gedeeld.

©WEI ZHENG

Van slimme assistent naar app‑regisseur

De evolutie van Gemini laat zien waar het naartoe gaat met AI in Android: niet langer een slimme praatpaal in de marge, maar een behoorlijk dominante regisseur van je app-gebruik. Vergelijk het met Siri's vernieuwde integratie in iOS 18 of de opkomende app-functies in Android 16 – allemaal gericht op een AI die niet alleen antwoordt, maar ook handelt.

Die verschuiving is logisch, maar dwingt ontwikkelaars én gebruikers om na te denken over de ethiek van assistentie. Want hoe vriendelijk een AI ook oogt, als die steeds meer kan, moet je ook scherper kijken naar wat je precies weggeeft.

Wat betekent dat concreet voor jou?

Als gebruiker hoef je je voorlopig geen zorgen te maken dat Gemini heimelijk je gesprekken opslaat of meeluistert zonder toestemming. Maar het blijft belangrijk om je instellingen te checken, zeker nu de AI standaard meer bevoegdheden krijgt. De tools om die macht te beperken zijn er gelukkig, je moet ze alleen wel even opzoeken.

Wil je dus de voordelen van Gemini benutten zonder je privacy op het spel te zetten? Check dan vóór 7 juli je instellingen en bepaal zelf hoeveel zeggenschap je de AI geeft. Zo houd je het beste van twee werelden: slimme hulp, zonder ongewenste inmenging.

Check dit vóór 7 juli

Vanaf 7 juli activeert Google automatisch nieuwe functies in Gemini. Wil je niet dat de AI toegang krijgt tot apps als WhatsApp of Telefoon? Ga dan naar de instellingen van de Gemini-app of bezoek gemini.google.com/apps. Daar kun je per app zelf aangeven of Gemini ermee mag werken.