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
Review Samsung Galaxy A56 – Weer een hit
© Rens Blom
Huis

Review Samsung Galaxy A56 – Weer een hit

De Galaxy A-serie levert Samsung al jaren verkoopknallers op, en grote kans dat ook de nieuwe Galaxy A56 een hit wordt. Dit toestel biedt namelijk een uitstekende prijs-kwaliteitverhouding en krijgt zes jaar updates. Lees alles over de smartphone in onze uitgebreide Samsung Galaxy A56 review.

Uitstekend
Conclusie

De Samsung Galaxy A56 is een typische smartphone voor het grote publiek. Hij laat geen steken vallen en blinkt eigenlijk ook nergens echt in uit. Het is gewoon een fijne smartphone met een goed scherm, lange accuduur en zes jaar updategarantie. Gelet op de straatprijs van circa 380 euro is de Galaxy A56 daarom een toestel met een uitstekende prijs-kwaliteitverhouding.

Plus- en minpunten
  • Functioneel, luxe ontwerp
  • Mooi scherm
  • Lange accuduur
  • Zes jaar updates
  • Geen microSD-kaartslot voor uitbreiding opslag
  • Macrocamera voegt weinig toe
  • Te veel nadruk op aanmaken Samsung-account

De Galaxy A-reeks van 2025 bestaat op moment van schrijven uit de A26, A36 en A56. Hoe hoger het getal, hoe completer en duurder het toestel. De adviesprijs van de A56 bedraagt 480 euro, maar na de release medio maart is de straatprijs van de smartphone eind april al gezakt naar 380 euro. Een veel vriendelijkere prijs. Ook de versie met meer opslagcapaciteit (256 GB in plaats van 128 GB) is al tientallen euro's in prijs gezakt.

©Rens Blom

Premium ontwerp

Kijk je naar de A56, dan kijk je zonder twijfel naar een moderne Samsung-smartphone. De A56 past precies in Samsungs straatje en dat vinden we helemaal prima, want het ontwerp komt luxe over en de smartphone houdt prettig vast. Ook fijn is dat de A56 waterdicht is en wat minder weegt dan zijn voorganger, de A55. Met 198 gram is het gewicht nu gangbaar voor een toestel met 6,7 inch-scherm. Door zijn afmetingen is de A56 wel lastig met één hand te bedienen. Daar staat tegenover dat het grote scherm zich goed leent voor het bekijken van filmpjes, het typen met twee handen en het spelen van games.

©Rens Blom

Het scherm bevalt ons sowieso erg goed. Het oledscherm heeft een Full-HD-resolutie, soepele 120Hz-verversingssnelheid en kan erg fel. De zomers aanvoelende dagen medio en eind april brachten een krachtig zonnetje met zich mee, maar we konden het scherm van de Galaxy A56 buiten goed aflezen.

Complete specificaties

Zoals we gewend zijn van de Galaxy A-serie, biedt ook de A56 een mooi totaalpakket aan functies voor een sympathieke prijs. Dat begint bij de processor. De nieuwe, door Samsung zelf ontwikkelde processor, is lekker snel en werkt samen met 8 GB werkgeheugen. Er zijn wat toestellen die beter omgaan met zware games, maar voor de meeste toepassingen is de A56 goed uitgerust.

©Rens Blom

De A56 heeft daarnaast ondersteuning voor e-sim (een digitale simkaart), lekker duidelijke luidsprekers en keuze uit 128 GB of 256 GB opslagcapaciteit. Omdat het prijsverschil tussen de twee opslagversies slechts enkele tientjes bedraagt, raden wij de meeste mensen aan om de 256GB-variant te kiezen. Waarom? Die heeft veel meer ruimte voor je apps, foto's, filmpjes en andere bestanden en niet te vergeten: updates die jarenlang beschikbaar komen. Omdat de smartphone geen microSD-kaartslot heeft, moet je het doen met de ingebouwde opslagcapaciteit. Als je de A56 jaren wilt gebruiken, lijkt het ons verstandig om eenmalig iets meer te betalen voor veel meer opslagruimte.

©Rens Blom

Snel opladen, voor Samsungs doen

Dan de accuduur, een punt waarop Galaxy A-smartphones al jaren (meer dan) prima scoren. De A56 zet die traditie voort. Hoewel de accucapaciteit met 5000 mAh zeker niet groter is dan gebruikelijk en het scherm met 6,7 inch van gangbare grootte is, weet de A56 toch een lange accuduur te realiseren. Wij hebben in de testperiode nooit moeite gehad om een lange dag door te komen, ook niet als we het toestel een uur als hotspot gebruikten om op onze laptop te kunnen internetten in de trein. Dat soort zaken trekken de smartphone-accu sneller leeg, maar de A56 is lekker zuinig.

Het opladen kan helaas niet draadloos, maar dat is een logische bezuiniging in een betaalbare smartphone. Opladen via de usb-c-kabel dus, die in de doos zit. De adapter dien je zelf te regelen. Het loont om een adapter te pakken of kopen die via het juiste protocol 45 watt of meer aan stroom levert. De Galaxy A45 kan namelijk laden met maximaal 45 watt. Dat is veel sneller dan de meeste andere Samsung-smartphones, waardoor de accu sneller vol is. In vergelijking met de concurrentie is 45 watt prima, maar niet bijzonder. Er zijn genoeg smartphones die 65 tot 100 watt aankunnen.

©Rens Blom

Camera's

Met de Galaxy A56 kun je mooie foto's schieten, vooral met de hoofdcamera van 50 megapixel. Die staat echt zijn mannetje. De groothoekcamera van 12 megapixel is minder goed, maar volstaat ook en legt een lekker wijd deel van de situatie vast. De macrocamera van 5 megapixel voegt naar onze mening weinig toe, maar zit ook niet in de weg. De A56 kan zoomen via de hoofdcamera, maar dan holt de kwaliteit wel achteruit.

De selfiecamera vinden we opvallend goed, wat een opsteker is voor wie graag selfies neemt of videogesprekken voert met zijn telefoon.

©Rens Blom

Van boven naar beneden: de hoofdcamera, groothoekcamera en een paar keer zoom.

Zes jaar updates

Een prettige gedachte bij de Galaxy A56 is dat Samsung zes jaar complete updates belooft. Je krijgt dus de komende jaren verschillende Android-upgrades en kunt ook zes jaar lang beveiligingsupdates verwachten. Erg netjes, gelet op de prijs van de telefoon.

©Rens Blom

Samsungs OneUI-softwareschil over Android heen is wat druk en wil héél graag dat je een Samsung-account aanmaakt. Dat is echter niet verplicht. OneUI biedt allerlei handigheidjes, waarvan een deel leunt op kunstmatige intelligentie (AI). Er valt veel te proberen.

Conclusie: Samsung Galaxy A56 kopen?

De Samsung Galaxy A56 is een typische smartphone voor het grote publiek. Hij laat geen steken vallen en blinkt eigenlijk ook nergens echt in uit. Het is gewoon een fijne smartphone met een goed scherm, lange accuduur en zes jaar updategarantie. Gelet op de straatprijs van circa 380 euro is de Galaxy A56 daarom een toestel met een uitstekende prijs-kwaliteitverhouding.

▼ Volgende artikel
Een vaatwasser die de vaat droogt: hoe doet-ie dat eigenlijk?
© Davizro Photography
Huis

Een vaatwasser die de vaat droogt: hoe doet-ie dat eigenlijk?

Bij het kiezen van de ideale vaatwasser zijn er heel wat zaken om op te letten. Eén daarvan is de droogtechniek die wordt toegepast. Er zijn grofweg drie methodes: ventilatiedroging, condensdroging en drogen met zeoliet. In dit artikel leggen we uit wat elke techniek precies inhoudt.

⏱ In dit artikel leggen we je alles uit over de verschillende droogtechnieken die vaatwasmachines kunnen gebruiken:

  • Drogen met de ventilatiedroogtechniek (verdamping)
  • Drogen met de condensdroogtechniek
  • Drogen met zeoliet

Ook interessant voor jou: De belangrijkste functies en programma’s van je vaatwasser uitgelegd

Schoon én droog

Een vaatwasser moet natuurlijk in de eerste plaats zorgen voor blinkend schone vaat. Maar minstens zo belangrijk is hoe goed hij alles droogt, want niets is zo irritant als bij het uitruimen alsnog de theedoek tevoorschijn moeten halen. Blijft er water achter op borden of in glazen, dan loop je bovendien het risico op schimmelvorming – en dat is allesbehalve fris. Ben je toe aan een nieuwe vaatwasser? Let dan zeker ook op de gebruikte droogtechniek.

Vaatwassers met ventilatiedroogtechniek

Een veelgebruikte manier om de vaat te drogen, is door het water te laten verdampen. Dit wordt ook wel de ventilatiedroogtechniek genoemd. Sommige vaatwassers hebben een mechanische arm die de deur automatisch opent zodra het programma is afgelopen. Het warme vocht in de machine kan dan vanzelf ontsnappen. Je kunt de deur natuurlijk ook handmatig openen, maar doe dat dan wel meteen na afloop van het programma. Omdat zowel de vaat als het water dan nog warm zijn, verdampt het vocht sneller dan wanneer je langer wacht.

Deze methode is het meest milieuvriendelijk, maar heeft ook een nadeel: het kan vrij lang duren voordat alles echt droog is. En soms blijft er toch nog vocht achter, waardoor je alsnog naar die theedoek moet grijpen.

©VLADYSLAV LEHIR

Vaatwassers met condensdroogtechniek

Een andere mogelijkheid is een vaatwasser met condensdroogtechniek. Deze methode is vooral geschikt als je vaak glaswerk, aardewerk of roestvrij staal reinigt. De warme, vochtige lucht in de machine slaat daarbij neer op de koelere wanden van de binnenruimte. Het gecondenseerde water wordt opgevangen en vervolgens weggepompt.

Het nadeel van deze techniek is dat de vaat vaak nog niet helemaal droog is wanneer het programma klaar is. Een theedoek blijft dus onmisbaar. Wil je toch profiteren van dit betaalbare systeem? Combineer het dan met handmatige ventilatie: zet de deur na afloop even op een kier zodat de stoom sneller kan ontsnappen en de vaat beter nadroogt.

Vaatwassers met zeoliet: hoe werkt dat?

De beste droogtechniek van dit moment? Dat is zonder twijfel zeolietdroging. Zeoliet is een mineraal dat warmte afgeeft zodra het in aanraking komt met water. Gebruikers zijn vaak laaiend enthousiast: volgens velen is hun vaat nog nooit zó goed droog uit de machine gekomen. Of het nu om plastic bakjes, glazen of borden gaat – alles komt er kurkdroog uit, ongeacht waar het staat in de vaatwasser. Niet gek dus dat modellen met deze techniek steeds populairder worden en steeds meer gemeengoed worden. Ze zijn dan ook bij diverse webwinkels te vinden.

Maar hoe werkt het precies? Onder in de vaatwasser liggen speciale zeolietkorrels. Zodra het programma is afgelopen en het water is afgevoerd, komen de korrels in actie. Ze geven warmte af aan de binnenruimte, waardoor de vaat efficiënt wordt gedroogd. Handig: de korrels regenereren zichzelf na elke wasbeurt. Je hoeft ze dus nooit te vervangen. Bovendien is dit systeem ook nog eens bijzonder energiezuinig.

Fijn: Vaatwassers met zeoliet zijn niet per se duurder dan de andere varianten. De prijs wordt mede bepaald door het type vaatwasser dat je aanschaft en de manier waarop je hem installeert.

VentilatieCondensZeoliet
✅ Meest eco-vriendelijk✅ Heel geschikt voor glas, aardewerk of staal✅ Vaat echt droog
❌ Drogen duurt lang❌ Vaat niet altijd helemaal droog✅ Energie-efficiënt
❌ Vaat niet altijd helemaal droog