← Back to CoursesStemExpert
StemExpert
Intermediate · Handboek · 27. Python: de basis
StemExpert · Brecht Corbeel · schoolium.me
StemExpert
I27. Python: de basis
IIntermediate · deel I7 · Programmeren

Handboek · hoofdstuk 27Python: de basis

Van blokken naar tekst: variabelen, rekenen, keuzes, lussen en foutmeldingen die je leert lezen

In Fundamental stapelde je blokken tot een programma, en in de vorige hoofdstukken las je al korte Python-programma's. Nu schrijf je ze zelf. Je zet een blokprogramma om in tekst, leert rekenen, kiezen en herhalen in Python, en vooral: je leert de foutmeldingen lezen, zodat een fout geen muur is maar een aanwijzing. Aan het eind schrijf je een rekenhulp voor het energiebudget van de klimaatmodule.

10× uitleg5× uitgewerkt voorbeeld1× proef2× ontleed1× naslag1× verhaal1× het geheel5× code17 opdrachten in het werkboek± 8 lestijden
Dezelfde simulatie twee keer: links in blokken, rechts in Python.
Dezelfde simulatie twee keer: links in blokken, rechts in Python.
Na dit hoofdstuk
Verhaal · 27.1

Een kerstproject dat wereldtaal werd

1/26

In december 1989 zocht de Nederlandse programmeur Guido van Rossum een project voor de kerstvakantie. Hij werkte bij het CWI, het onderzoeksinstituut voor wiskunde en informatica in Amsterdam, aan de taal ABC, die bedoeld was om programmeren makkelijk te maken. Hij begon aan een opvolger die even leesbaar moest zijn maar ook echt werk moest kunnen doen. De naam haalde hij niet bij de slang, maar bij de Britse comedyreeks Monty Python's Flying Circus.

In februari 1991 zette hij de eerste versie online. Andere programmeurs begonnen mee te bouwen, en Python groeide uit tot een van de populairste programmeertalen ter wereld. In december 2008 verscheen Python 3, dat een paar oude keuzes rechtzette; sinds 2020 wordt het oude Python 2 niet meer onderhouden. Alles in dit boek is Python 3.

Wat Python bijzonder maakt, is de leesbaarheid. Er zijn geen accolades of puntkomma's zoals in C++; de structuur zie je aan het inspringen. Een van de richtlijnen van de taal zegt het kort: "Readability counts." Een programma schrijf je één keer, maar lees je tientallen keren, ook als je een fout zoekt.

Wetenschappers en ingenieurs gebruiken Python voor bijna alles wat met data te maken heeft. De rekenbibliotheek numpy, die je in hoofdstuk 4 en 22 al tegenkwam, zat in de software van de eerste meting van zwaartekrachtgolven (2015) en van de eerste foto van een zwart gat (2019).

Waarom dit hoofdstuk ertoe doet

Blokken zijn ideaal om te leren denken als een programmeur, maar een blokprogramma van honderd regels wordt een onoverzichtelijke toren. In tekst schrijf je sneller, kan je code kopiëren, delen en vergelijken, en gebruik je bibliotheken voor grafieken, data en AI. De klimaatmodule en later het brein van het station draaien op zulke code.

Een programma lezen is net zo belangrijk als het schrijven.
Een programma lezen is net zo belangrijk als het schrijven.
Uitleg · 27.2

Wat je al kan, en hoe je Python draait

2/26
wat je al kanwat er nu bijkomt
een algoritme als stroomdiagram tekenen en naspelen met een trace-tabel (F22)hetzelfde algoritme in Python, en lussen naspelen met een trace-tabel
blokken stapelen: volgorde, herhaal, als ... dan ... anders, variabelen (F23)dezelfde bouwstenen als tekst: regels, for, while, if, =
een microcontroller programmeren in C++ met setup() en loop() (F24, F25)Python op de computer; C++ voor de Arduino komt terug in hoofdstuk 29
korte Python-programma's lezen: kalibreren (hoofdstuk 3), het energiebudget (hoofdstuk 20), een NTC ijken (hoofdstuk 22)zulke programma's zelf schrijven, fouten lezen en verbeteren

Een Python-programma is een gewoon tekstbestand met de extensie .py. Je schrijft het in een editor. Voor beginners is Thonny handig (gratis, met Python erbij); IDLE zit bij elke installatie van Python; wie verder wil, gebruikt VS Code. Met de knop Run (of F5) geef je het bestand aan de interpreter: het programma dat je tekst leest en regel per regel uitvoert. Wat print() toont, en eventuele foutmeldingen, verschijnen in het uitvoervenster.

Onderaan in Thonny en IDLE zit ook de interactieve shell, met de prompt >>>. Daar typ je één regel en zie je meteen de uitkomst: ideaal om iets uit te proberen. Een programma bewaar je wel altijd in een bestand.

Interpreter tegenover compiler

Je Arduino-programma (F24) werd eerst volledig vertaald naar machinetaal (compileren) en dan naar het bordje gestuurd. Python leest je bestand, controleert de schrijfwijze en voert het meteen uit, regel per regel. Dat maakt uitproberen snel, maar een tikfout in een naam op regel 40 merk je pas als Python regel 40 bereikt. Alleen fouten in de schrijfwijze zelf ziet Python vooraf, vóór er iets draait.

Bestandsnamen

Geef je bestanden korte namen zonder spaties: budget.py, kas_simulatie.py. Noem een eigen bestand nooit zoals een bibliotheek (random.py, math.py, csv.py): dan laadt Python jouw bestand in plaats van de bibliotheek.

1 editortekst die je typt enbewaart als budget.py2 Pythonleest het programma envoert het regel perregel uit3 uitvoerwat print() toont, ofeen foutmeldinginteractieve shell>>> 7 / 2geeft meteen 3.5één regel uitprobereneen programma
Een programma bewaar je als bestand; in de shell probeer je één regel uit.
Code · 27.3

Van blokken naar tekst: de meetkas als simulatie

3/26

In F23 bouwde je een simulatie van de meetkas in blokken: het bodemvocht daalt elk uur 5 procentpunt, en onder 30 % geeft de pomp een beurt van 30 s (240 mL), die het vocht 16 procentpunt hoger maakt. Hier staat hetzelfde programma in Python. Lees het naast de blokken, regel per blok.

Pythonkas_simulatie.py14 regelsDownload
# kas_simulatie.py - de meetkas uit F23, nu in Pythonvocht = 50              # bodemvocht (%)water = 30              # water in het reservoir (L)beurten = 0             # teller: aantal pompbeurten for uur in range(48):   # een ronde is een uur    vocht = vocht - 5   # de planten drinken    if vocht < 30:        vocht = vocht + 16          # pompbeurt van 30 s        water = water - 0.24        # 240 mL        beurten = beurten + 1 print("beurten:", beurten)print("water over:", round(water, 2), "L")
wanneer opwordt gekliktmaakvocht50maakwater30maakbeurten0herhaal48verandervochtmet-5alsvocht<30danverandervochtmet16veranderwatermet-0.24veranderbeurtenmet1zegvoegbeurten: enbeurtensamen
Hetzelfde algoritme in blokken; de wachttijd uit F23 is weggelaten.

Uitvoer:

beurten: 14
water over: 26.64 L
blok (Scratch)Pythonwat er gebeurt
wanneer op de groene vlag wordt geklikt(het programma starten)Python begint gewoon bovenaan
maak [vocht] (50)vocht = 50de naam vocht wijst naar 50
herhaal (48)for uur in range(48):48 rondes; uur telt mee: 0, 1, ..., 47
verander [vocht] met (−5)vocht = vocht - 5nieuwe waarde = oude waarde − 5
als <vocht < 30> danif vocht < 30:alleen als de voorwaarde waar is
de mond van een C-blokinspringen (4 spaties)wat ingesprongen staat, hoort bij de lus of de keuze
zeg (voeg [beurten: ] en (beurten) samen)print("beurten:", beurten)tekst en waarde in de uitvoer

Drie dingen vallen op. Een C-blok wordt een regel die eindigt op een dubbelepunt, gevolgd door regels die inspringen: zo weet Python wat in de lus of in de keuze hoort. Een maak-blok en een verander-blok worden allebei een regel met =. En alles achter een # is commentaar: uitleg voor mensen, Python slaat het over. In Scratch gebruikte je 'wacht 0.2 sec.' om de simulatie te zien lopen; in Python doet import time bovenaan en time.sleep(0.2) in de lus hetzelfde.

Ontleed · 27.4

Een Python-programma ontleed

4/26

Hetzelfde programma, zonder het commentaar achter de regels. De regelnummers staan er niet echt in: editors tonen ze in de kantlijn, en foutmeldingen verwijzen ernaar.

1# kas_simulatie.py - de meetkas uit F23, nu in Python2vocht = 503water = 304beurten = 056for uur in range(48):7vocht = vocht - 58if vocht < 30:9vocht = vocht + 1610water = water - 0.2411beurten = beurten + 11213print("beurten:", beurten)14print("water over:", round(water, 2), "L")
Kleuren zoals in een editor: sleutelwoorden, ingebouwde functies, tekst en commentaar.
Wijs een nummer aan: de figuur zoomt in. Klik om vast te zetten.
  1. 1
    Commentaar

    Alles na # tot het einde van de regel. Zet bovenaan wat het programma doet; leg uit waarom, niet wat er al staat.

  2. 2
    Toekenning

    vocht = 50: de naam vocht wijst voortaan naar de waarde 50. Het isgelijkteken betekent 'wordt', niet 'is gelijk aan'.

  3. 3
    for-lus

    range(48) levert 0, 1, ..., 47: de lus loopt 48 keer, en uur krijgt elke ronde de volgende waarde.

  4. 4
    Keuze met een voorwaarde

    vocht < 30 is True of False. De dubbelepunt kondigt een blok aan dat alleen bij True draait.

  5. 5
    Inspringen

    Vier spaties: hoort bij de for. Acht spaties: hoort bij de if in de for. Het inspringen is de mond van het C-blok.

  6. 6
    Na de lus

    Niet ingesprongen: deze regel draait pas als de 48 rondes voorbij zijn, precies één keer.

  7. 7
    Functies aanroepen

    round(water, 2) geeft water afgerond op 2 decimalen; print() toont al zijn argumenten, gescheiden door een spatie.

Uitleg · 27.5

Variabelen: een naam voor een waarde

5/26

Een variabele is een naam die naar een waarde wijst. Je maakt ze met een toekenning: links de naam, dan =, rechts de waarde of een berekening. Python rekent eerst de rechterkant uit en hangt dan de naam aan het resultaat. Daarom is vocht = vocht - 5 geen onzin: neem de huidige waarde van vocht (50), trek er 5 af, en laat vocht voortaan naar 45 wijzen. Korter kan ook: vocht -= 5, beurten += 1.

In F23 dacht je aan een variabele als een doos. In Python klopt een naamkaartje beter: de waarde bestaat, en de naam hangt eraan. Voor getallen maakt dat geen verschil, voor lijsten (hoofdstuk 28) wel.

Regels voor namen. Letters, cijfers en een liggend streepje; niet beginnen met een cijfer; geen spaties. Hoofdletters tellen: Vocht en vocht zijn twee verschillende namen. Woorden van de taal zelf (for, if, while, ...) mogen niet. Kies namen die zeggen wat erin zit, in kleine letters met streepjes: verbruik_dag, wh_per_wp. Een programma met x, y en z kan je volgende week zelf niet meer lezen. In dit boek zijn de namen Nederlands en de sleutelwoorden van Python Engels.

"= betekent is gelijk aan"

In de wiskunde is een vergelijking zonder oplossing. In Python is x = x + 1 een opdracht: 'x wordt x plus 1'. Wil je testen of twee waarden gelijk zijn, dan schrijf je twee isgelijktekens: vocht == 30. Dat geeft True of False en verandert niets.

na de eerste drie toekenningenna vocht = vocht − 5vocht50water30beurten0vocht45water30beurten050geen naam wijst nog naar 50:Python ruimt die waarde op
Een nieuwe toekenning verlegt de pijl; de oude waarde 50 wordt niet meer gebruikt.
Proef · 27.6

Rekent Python zoals jij? Voorspel, probeer, verklaar

6/26
Onderzoeksvraag

Wat antwoordt Python op 7 / 2, 7 // 2, "7" + "2", 0,1 + 0,2 en 3269,5 > 3000?

Materiaal
  • computer met Python 3 (Thonny of IDLE)
  • papier en pen voor de voorspellingen
Eerst voorspellen op papier, dan pas typen: zo zie je waar Python anders rekent dan jij.
Eerst voorspellen op papier, dan pas typen: zo zie je waar Python anders rekent dan jij.
Werkwijze
  1. 1Open de interactieve shell (het venster met >>>).
  2. 2Schrijf voor elke regel uit de waarneming eerst op papier wat je verwacht. Let op de aanhalingstekens.
  3. 3Typ de regels één voor één en druk telkens op Enter. Noteer wat Python antwoordt.
  4. 4Omcirkel elke uitkomst die afwijkt van je voorspelling.
  5. 5Vraag met type(...) het type op van de uitkomsten die je verrasten.
Waarneming

Zo antwoordt Python (Python 3.13):

>>> 7 / 2
3.5
>>> 7 // 2
3
>>> 10 / 5
2.0
>>> "7" + "2"
'72'
>>> "7" * 3
'777'
>>> 0.1 + 0.2
0.30000000000000004
>>> 3269.5 > 3000
True
>>> type(7 / 2)
<class 'float'>
>>> type(3269.5 > 3000)
<class 'bool'>
Verklaring

Elke waarde heeft een type, en de bewerking hangt af van het type. / geeft altijd een kommagetal (float), ook als de deling opgaat. // geeft het gehele deel. Tussen aanhalingstekens staat tekst (str): + plakt tekst aan elkaar en * 3 herhaalt ze. Een vergelijking levert True of False (bool).

En 0,1 + 0,2? Een computer bewaart kommagetallen in het tweetallig stelsel (hoofdstuk 25). Zoals 1/3 in het tientallig stelsel nooit precies opgaat (0,333...), gaat 0,1 in het tweetallig stelsel niet op. De fout zit in het zestiende cijfer: voor metingen onbelangrijk, maar test kommagetallen daarom nooit met ==. Rond af of vergelijk met een kleine marge.

Uitleg · 27.7

Types: int, float, str en bool

7/26
typenaamvoorbeeldengebruik
intgeheel getal (integer)16, -3, 0, 2457tellen: beurten, dagen, lichturen, ADC-waarden
floatkommagetal (floating point)3.5, 1400.0, 2.99, 1e-9meten en rekenen: vermogen, temperatuur, pH
strtekst (string)"kas", '16', "" (lege tekst)namen, berichten, alles wat input() binnenkrijgt
boolwaarheidswaarde (boolean)True, Falseuitkomst van een vergelijking: vocht < 30

Python beslist het type zelf, uit de schrijfwijze: 16 is een int, 16.0 een float, "16" tekst. Een decimaal getal schrijf je in Python altijd met een punt, zoals in Scratch. Omzetten doe je met een functie die de naam van het type draagt:

>>> int("16") + 4
20
>>> float("1.25") * 1400
1750.0
>>> str(16) + " lichturen"
'16 lichturen'
>>> int(7.9)
7
>>> round(7.9)
8
>>> float(3)
3.0

Let op het verschil tussen int(7.9) en round(7.9): int() kapt de decimalen af, round() rondt af. Tekst die geen getal voorstelt, kan je niet omzetten: float("3,5") geeft een foutmelding, want Python kent de decimale komma niet. Vervang eerst de komma door een punt.

type() als detective

Doet een berekening iets vreemds, vraag dan het type op: type(x). Een getal dat stiekem tekst is ('25' in plaats van 25), verklaart de helft van alle beginnersfouten met input().

"16"strint()16intfloat()16.0floatstr()"16.0"str"3,5"strfloat()ValueErroreen komma kent float() niet"3,5"str.replace(",", ".")"3.5"strfloat()3.5float
int(), float() en str() zetten een waarde om; een decimale komma moet eerst een punt worden.
Uitleg · 27.8

Rekenen: van + tot **

8/26

Python rekent zoals een rekenmachine, met een paar tekens die je moet kennen:

tekenbewerkingvoorbeelduitkomstopmerking
+optellen17 + 522
-aftrekken17 - 512
*vermenigvuldigen17 * 585geen × of ·
/delen17 / 53.4altijd een float, ook bij 10 / 5
//gehele deling17 // 53afgerond naar beneden
%rest (modulo)17 % 52wat overblijft na de gehele deling
**macht2 ** 101024niet ^ (dat is iets anders in Python)

Met // en % reken je met hele stukken en resten: minuten naar uren en minuten, plantplaatsen over goten verdelen, testen of een getal even is (n % 2 == 0). De volgorde is die van de wiskunde: eerst machten, dan vermenigvuldigen en delen, dan optellen en aftrekken, van links naar rechts; haakjes gaan voor alles.

uitdrukkinguitkomstwaarom
2 + 3 * 414eerst *, dan +
(2 + 3) * 420haakjes eerst
2 * 3 ** 218eerst de macht: 3 ** 2 = 9
-2 ** 2-4de macht gaat vóór het minteken: −(2²)
(-2) ** 24met haakjes: (−2)²
7 - 4 - 12van links naar rechts
-7 // 2-4naar beneden afgerond: −3,5 wordt −4

Voor wortels, sinussen en laad je de bibliotheek math:

>>> import math
>>> math.sqrt(1.65 ** 2 + 1.00 ** 2)
1.9293781381574737
>>> round(math.pi, 4)
3.1416
>>> math.sin(math.radians(30))
0.49999999999999994

De eerste regel is de diagonaal van een zonnepaneel van 1,65 m op 1,00 m (stelling van Pythagoras). Let op de laatste: math.sin rekent in radialen, dus eerst omzetten; en ook hier is het resultaat een kommagetal met een klein foutje in de laatste cijfers.

groep 1groep 2groep 3rest17 // 5 = 3drie volle groepen van vijf17 % 5 = 2twee blijven over (de rest)17 / 5 = 3.4gewoon delen: altijd een float17 blokjes in groepen van 5
Gehele deling en rest: 17 = 3 · 5 + 2.
Uitgewerkt voorbeeld · 27.9

Seconden omrekenen naar een kloktijd

9/26

De datalogger van de klimaatmodule telt de seconden sinds middernacht. Een meting heeft het tijdstip 49 317. Schrijf een programma dat dat omzet naar uren, minuten en seconden.

Gegeven
  • t = 49 317 s sinds middernacht
  • 1 h = 3600 s, 1 min = 60 s
Gevraagd
  • uren, minuten en seconden, getoond als 13:41:57
Oplossing
  1. 1
    Uren. Hoeveel volle uren zitten er in t? Dat is de gehele deling: uren = t // 3600 geeft 13.
  2. 2
    Wat overblijft. De rest na die volle uren: rest = t % 3600 geeft 2517 s.
  3. 3
    Minuten en seconden. Hetzelfde met 60: rest // 60 is 41 minuten, rest % 60 is 57 seconden.
  4. 4
    Tonen. Met een f-string en :02d (twee cijfers, aanvullen met een nul) ziet het eruit als een klok:
    t = 49317
    uren = t // 3600
    rest = t % 3600
    minuten = rest // 60
    seconden = rest % 60
    print(f"{uren:02d}:{minuten:02d}:{seconden:02d}")
    13:41:57
Antwoord
Tijdstip 49 317 s is 13:41:57.
Klopt dit? Terugrekenen: . Klopt. En een test op de randen: t = 0 moet 00:00:00 geven en t = 86 399 (de laatste seconde van de dag) 23:59:59.
Code · 27.10

Uitvoer: print() en f-strings

10/26

print() toont al zijn argumenten, met een spatie ertussen, en begint daarna een nieuwe regel. Voor nette uitvoer gebruik je een f-string: een tekst met een f vóór het aanhalingsteken, waarin je waarden tussen accolades zet. Achter een dubbelepunt in de accolades staat de opmaak: {zon:.0f} betekent 'zon als kommagetal met 0 decimalen'.

Pythonuitvoer.py13 regelsDownload
# uitvoer.py - getallen netjes tonenzon = 1400 * 2.99       # Wh per dag in maart (4 panelen van 350 Wp)verbruik = 3269.5       # Wh per dagwater = 30 - 0.24 - 0.24 - 0.24print(water)print("water:", round(water, 2), "L")print(f"zon: {zon:.0f} Wh, verbruik: {verbruik:.1f} Wh")print(f"saldo: {zon - verbruik:+.1f} Wh")print(f"dekking: {zon / verbruik:.1%}")kwh = f"{verbruik / 1000:.2f}".replace(".", ",")print("verbruik:", kwh, "kWh per dag")print(f"{'lampen':<10}{3040:>6} Wh")print(f"{'pomp':<10}{48:>6} Wh")

Uitvoer:

29.280000000000005
water: 29.28 L
zon: 4186 Wh, verbruik: 3269.5 Wh
saldo: +916.5 Wh
dekking: 128.0%
verbruik: 3,27 kWh per dag
lampen      3040 Wh
pomp          48 Wh

De eerste regel toont waarom je afrondt: drie keer 0,24 aftrekken geeft een getal met een foutje in de vijftiende decimaal. round(water, 2) rekent verder met de afgeronde waarde; een f-string rondt alleen af bij het tonen en laat de variabele zelf ongemoeid.

waardef-stringresultaatbetekenis
x = 3269.5f"{x:.2f}"'3269.50'2 decimalen
x = 3269.5f"{x:.0f}"'3270'afgerond op een geheel getal
x = 3269.5f"{x:10.1f}"'    3269.5'10 tekens breed, 1 decimaal (rechts uitgelijnd)
x = 916.5f"{x:+.1f}"'+916.5'altijd een teken, ook +
x = 0.535f"{x:.0%}"'54%'als procent (maal 100)
s = "pomp"f"{s:<10}|"'pomp      |'10 tekens breed, links uitgelijnd
n = 48f"{n:>5}"'   48'5 tekens breed, rechts uitgelijnd
n = 48f"{n:05d}"'00048'aanvullen met nullen
Een decimale komma tonen

Python schrijft getallen altijd met een punt. Voor een Nederlandstalig verslag maak je eerst de tekst en vervang je dan de punt: f"{x:.2f}".replace(".", ","). Doe dat alleen bij het tonen: met de tekst "3,27" kan je niet meer rekenen.

Afronden op ,5

Python rondt een getal dat precies op ,5 eindigt af naar het even getal: round(2.5) geeft 2, round(3.5) geeft 4. Zo vallen afrondingsfouten bij veel getallen tegen elkaar weg. Bij metingen merk je er bijna nooit iets van.

Uitleg · 27.11

Invoer: input() geeft altijd tekst

11/26

Met input() vraagt een programma iets aan de gebruiker. Het toont de tekst tussen de haakjes, wacht tot de gebruiker iets typt en op Enter drukt, en geeft wat getypt werd terug als tekst. Ook als de gebruiker 30 typt, krijg je "30". Om ermee te rekenen, zet je het om met int() of float(). Wie een decimale komma typt, vang je op met .replace(",", "."):

# reservoir.py - hoe lang doet het reservoir van de meetkas het?
inhoud = float(input("Inhoud van het reservoir (L)? ").replace(",", "."))
verbruik = float(input("Verbruik per dag (L)? ").replace(",", "."))
dagen = inhoud // verbruik
print(f"Het reservoir houdt {dagen:.0f} volle dagen.")

Zo ziet een sessie eruit (het programma is gedraaid; de gebruiker typte 30 en 1,8):

Inhoud van het reservoir (L)? 30
Verbruik per dag (L)? 1,8
Het reservoir houdt 16 volle dagen.

Wat gebeurt er met de tekst voor ze een getal wordt? In de shell kan je het stap voor stap nagaan, met een variabele in de plaats van input():

>>> tekst = "1,8"
>>> type(tekst)
<class 'str'>
>>> tekst * 2
'1,81,8'
>>> tekst.replace(",", ".")
'1.8'
>>> float(tekst.replace(",", "."))
1.8
>>> 30 // float(tekst.replace(",", "."))
16.0
Programma's met input() in dit boek

De programma's in dit boek worden gedraaid terwijl de pagina's gemaakt worden, en dan zit er niemand aan het toetsenbord. Waar een programma invoer nodig heeft, staat de invoer daarom in een variabele, met de echte input()-regel als commentaar ernaast. Wil je het zelf interactief maken, dan wissel je die twee om.

Inhoud van het reservoir (L)? 30input(): vraag tonen en wachtenVerbruik per dag (L)? 1,8input() geeft de tekst "1,8" terugHet reservoir houdt 16 volle dagen.print(): het resultaatin groen: wat de gebruiker typt (en afsluit met Enter)
Wat de gebruiker typt, komt als tekst binnen: eerst omzetten, dan rekenen.
Code · 27.12

Voorwaarden: if, elif en else

12/26

Een keuze begint met if, een voorwaarde en een dubbelepunt. Het ingesprongen blok eronder draait alleen als de voorwaarde waar is. Met elif ('else if') test je een tweede voorwaarde als de eerste niet waar was, met else vang je alles op wat overblijft. Python test van boven naar onder en voert alleen het eerste blok uit waarvan de voorwaarde waar is.

Vergelijken doe je met == (gelijk), != (niet gelijk), <, <=, > en >=. Het programma is het energiebeheer van de klimaatmodule uit hoofdstuk 20: de groeilampen zijn de last die je afschakelt als de batterij leegloopt.

Pythonenergiebeheer.py13 regelsDownload
# energiebeheer.py - de groeilampen als afschakelbare last (hoofdstuk 20)laadtoestand = 30       # procentzon = 350               # vermogen van de zonnepanelen op dit moment (W) if laadtoestand > 40:    print("lampen volgens het schema")elif laadtoestand > 20:    if zon > 200:        print("lampen alleen op zonnestroom")    else:        print("lampen uit: te weinig zon")else:    print("lampen uit: batterij onder 20 %")
lees laadtoestand en zonlaadtoestand >40?jalampen volgenshet schemaneelaadtoestand >20?neelampen uit:batterij onder20 %jazon > 200 W?jalampen alleen opzonnestroomneelampen uit: te weinigzon
Elke ruit wordt een if of elif; de pijl naar rechts is het ingesprongen blok.

Uitvoer voor vier toestanden (telkens de eerste twee regels aangepast):

laadtoestandzonuitvoer
55 %350 Wlampen volgens het schema
30 %350 Wlampen alleen op zonnestroom
30 %120 Wlampen uit: te weinig zon
12 %400 Wlampen uit: batterij onder 20 %

Er staat een if ín een elif: een geneste keuze, met acht spaties. Het werkt, maar het is omslachtig. Met and kan het korter (volgende blad).

De volgorde van elif

Zet de strengste voorwaarde bovenaan. Stond laadtoestand > 20 vóór laadtoestand > 40, dan zou een volle batterij ook in de tweede tak belanden: bij 55 % is 55 > 20 al waar, en de rest wordt nooit meer getest.

Uitleg · 27.13

and, or en not: voorwaarden combineren

13/26

Met and is een samengestelde voorwaarde alleen waar als beide delen waar zijn; met or als minstens één deel waar is; not keert om. Het is dezelfde logica als schakelaars in serie en parallel (F18). Het energiebeheer wordt er korter mee:

if laadtoestand > 40:
    print("lampen volgens het schema")
elif laadtoestand > 20 and zon > 200:
    print("lampen alleen op zonnestroom")
else:
    print("lampen uit")
aba and ba or bnot a
TrueTrueTrueTrueFalse
TrueFalseFalseTrueFalse
FalseTrueFalseTrueTrue
FalseFalseFalseFalseTrue

Python kent ook een kettingvergelijking, zoals in de wiskunde: 5.5 <= ph <= 6.5 betekent 5.5 <= ph and ph <= 6.5. De volgorde van voorrang is: eerst vergelijken, dan not, dan and, dan or. Twijfel je, zet haakjes: (a or b) and c is iets anders dan a or (b and c).

"x == 1 or 2" test of x 1 of 2 is

Python leest x == 1 or 2 als (x == 1) or 2. Als x niet 1 is, wordt de uitkomst 2, en een getal dat geen nul is, telt als waar. De test is dus altijd waar, ook voor x = 5. Schrijf de vergelijking twee keer: x == 1 or x == 2.

aba and b: in serieaba or b: parallel
Een gesloten schakelaar is True: in serie brandt de lamp alleen met a én b, parallel met a of b.
Uitgewerkt voorbeeld · 27.14

pH en EC van de voedingsoplossing bewaken

14/26

De voedingsoplossing van de klimaatmodule moet een pH hebben tussen 5,5 en 6,5 (hoofdstuk 15) en een EC tussen 1,2 en 1,8 mS/cm (hoofdstuk 13). Schrijf een programma dat bij elke meting zegt wat er moet gebeuren. Kunnen twee problemen tegelijk voorkomen?

Gegeven
  • pH: in orde van 5,5 tot 6,5; te hoog: pH-min doseren; te laag: dosering controleren
  • EC: in orde van 1,2 tot 1,8 mS/cm; te laag: stamoplossing A en B bijdoseren; te hoog: aanlengen met regenwater
Gevraagd
  • een programma dat per meting de juiste berichten toont
Oplossing
  1. 1
    Eerst het normale geval. Alles in orde betekent: pH in het bereik en EC in het bereik. Met kettingvergelijkingen: 5.5 <= ph <= 6.5 and 1.2 <= ec <= 1.8.
  2. 2
    Anders: twee aparte vragen. pH en EC hangen niet van elkaar af: een oplossing kan tegelijk een te hoge pH én een te lage EC hebben. Daarom twee losse keuzes na elkaar (if ... if), geen elif tussen pH en EC. Binnen elke meting sluiten 'te hoog' en 'te laag' elkaar wel uit: daar past elif.
  3. 3
    Het programma:
    # bewaking.py - pH en EC van de voedingsoplossing (hoofdstukken 13 en 15)
    ph = 6.7
    ec = 1.1                # mS/cm bij 25 graden
    
    if 5.5 <= ph <= 6.5 and 1.2 <= ec <= 1.8:
        print("voedingsoplossing in orde")
    else:
        if ph > 6.5:
            print(f"pH {ph}: te hoog, pH-min doseren")
        elif ph < 5.5:
            print(f"pH {ph}: te laag, dosering controleren")
        if ec < 1.2:
            print(f"EC {ec}: te laag, stamoplossing A en B bijdoseren")
        elif ec > 1.8:
            print(f"EC {ec}: te hoog, aanlengen met regenwater")
  4. 4
    Testen met vier metingen, gekozen zodat elke tak minstens één keer draait:
    pHECuitvoer
    6,71,1pH 6.7: te hoog, pH-min doseren
    EC 1.1: te laag, stamoplossing A en B bijdoseren
    5,91,4voedingsoplossing in orde
    6,21,9EC 1.9: te hoog, aanlengen met regenwater
    5,31,5pH 5.3: te laag, dosering controleren
Antwoord
Het programma toont 'voedingsoplossing in orde' of een bericht per probleem. Bij pH 6,7 en EC 1,1 verschijnen twee berichten, omdat pH en EC met twee losse if-blokken getest worden.
Klopt dit? Test altijd de grenzen: bij pH 6,5 moet 'in orde' komen (6.5 <= 6.5 is waar), bij 6,51 niet. En test een geval per tak. Een tak die je nooit ziet draaien, kan een fout bevatten die pas maanden later opduikt.
Uitleg · 27.15

for-lussen en range()

15/26

Een for-lus herhaalt een blok voor elke waarde uit een reeks. De reeks komt meestal van range():

  • range(5): 0, 1, 2, 3, 4. Vijf waarden, beginnend bij 0: de stopwaarde doet niet mee.
  • range(2, 11, 3): start 2, stop 11, stap 3: 2, 5, 8.
  • range(10, 0, -3): met een negatieve stap tel je af: 10, 7, 4, 1.

De lusvariabele (hieronder uur) krijgt elke ronde de volgende waarde. Een for-lus kan ook over een vaste reeks waarden lopen, tussen haakjes; in hoofdstuk 28 wordt dat een lijst. En een lus mag in een lus staan: de binnenste loopt dan helemaal rond voor elke ronde van de buitenste.

for uur in range(6, 22, 3):
    print(uur, end=" ")
print()
for temp in (18, 22.5, 27):
    print(temp, "graden")
for dag in range(1, 3):
    for uur in range(0, 24, 8):
        print("dag", dag, "uur", uur)
6 9 12 15 18 21 
18 graden
22.5 graden
27 graden
dag 1 uur 0
dag 1 uur 8
dag 1 uur 16
dag 2 uur 0
dag 2 uur 8
dag 2 uur 16

end=" " zet een spatie in plaats van een nieuwe regel achter de uitvoer; de lege print() daarna sluit de regel af.

Blokken en lussen

herhaal (4) wordt for i in range(4):. herhaal tot een voorwaarde wordt een while met de omgekeerde voorwaarde (volgende bladen). Het eindeloze herhaal wordt while True:, zoals de loop() van een Arduino.

range(5)0123456789101112range(2, 11, 3)0123456789101112range(10, 0, -3)0123456789101112gevuld: wat range() geeft · open: de stopwaarde (doet niet mee)
Gevulde bolletjes doen mee; het open bolletje is de stopwaarde, die er net niet meer bij hoort.
for i in range(4):herhaal4zegHallo!1sec.while tijd != 0:herhaal tottijd=0verandertijdmet-1while True:herhaalvolgend uiterlijk
De drie lussen van Scratch, met erboven hun vorm in Python.
Code · 27.16

Optellen in een lus: het verbruik van een dag

16/26

Een heel nuttig patroon: een ophoper. Je begint met totaal = 0 vóór de lus, telt er in de lus telkens iets bij, en gebruikt het resultaat ná de lus. Hier telt de lus het verbruik van de klimaatmodule uur per uur op: 16 lichturen met gemiddeld 201,6 W en 8 nachturen met 5,5 W (hoofdstuk 20). Elk uur levert zijn vermogen maal één uur, dus zoveel wattuur.

Pythondagverbruik.py12 regelsDownload
# dagverbruik.py - het verbruik van de klimaatmodule uur per uur optellenp_licht = 201.6         # W, gemiddeld tijdens de 16 lichturen (lampen, pomp, sensoren, ventilatie)p_nacht = 5.5           # W, 's nachts (sensoren, ventilator, batterijbeheer)totaal = 0              # Wh: hier telt de lus alles bij op for uur in range(24):    if 6 <= uur < 22:   # lampen van 6 tot 22 uur (zomertijd)        totaal = totaal + p_licht    else:        totaal = totaal + p_nacht print(f"verbruik per dag: {totaal:.1f} Wh")
024681012141618202224050100150200250uurvermogen (W)16 × 201,6 Whnacht: 5,5 Wvermogen van de klimaatmodule
Elke ronde van de lus is één rechthoekje van één uur breed; de lus telt de oppervlakte op.

Uitvoer:

verbruik per dag: 3269.6 Wh

Hoofdstuk 20 kwam op 3269,5 Wh: het verschil van 0,1 Wh komt doordat 201,6 W zelf een afgerond gemiddelde is. De voorwaarde 6 <= uur < 22 is een kettingvergelijking: uur 6 telt mee, uur 22 niet. Zo zijn het precies 16 uren (6 tot en met 21).

De beginwaarde hoort vóór de lus

Staat totaal = 0 ín de lus, dan begin je elke ronde opnieuw bij nul en houd je alleen het laatste uur over (5,5 Wh). Het is dezelfde fout als 'maak score 0' in de lus van een Scratch-script.

Uitgewerkt voorbeeld · 27.17

Een lus naspelen met een trace-tabel

17/26

Speel de kas-simulatie van het begin van dit hoofdstuk na voor de eerste elf uren. Na hoeveel uur komt de eerste pompbeurt, en om de hoeveel uur volgen de andere?

06121824303642480102030405060tijd (h)bodemvocht (%)drempel 30 %vocht na elke ronde
De zaagtand van de simulatie: telkens 5 omlaag, en een sprong van 16 bij elke beurt.
Gegeven
  • het programma kas_simulatie.py
  • start: vocht 50, water 30, beurten 0
Gevraagd
  • een trace-tabel met de waarden na elke ronde
  • het ritme van de pompbeurten
Oplossing
  1. 1
    Kolommen kiezen. Eén kolom per variabele die verandert (vocht, water, beurten), plus de lusvariabele en de uitkomst van de voorwaarde. Zo zie je niet alleen de waarden, maar ook waarom ze veranderen.
  2. 2
    Rij per ronde invullen, precies in de volgorde van het programma: eerst −5, dan de test, dan eventueel de beurt.
    uurvocht bij de startna vocht − 5vocht < 30?vocht na de rondewater (L)beurten
    05045nee4530,000
    14540nee4030,000
    24035nee3530,000
    33530nee3030,000
    43025ja4129,761
    54136nee3629,761
    63631nee3129,761
    73126ja4229,522
    84237nee3729,522
    93732nee3229,522
    103227ja4329,283
    ...
    473934nee3426,6414
  3. 3
    De grens. In de rij uur = 3 is het vocht precies 30. 30 < 30 is False: nog geen beurt. Pas in de rij uur = 4 zakt het naar 25 en volgt de eerste beurt.
  4. 4
    Het ritme. Na een beurt staat het vocht op 41. Na drie rondes is het 26: opnieuw een beurt. Dat geeft 42, dan 27, dan 43: elke beurt komt het vocht 1 procentpunt hoger uit, tot het op een keer na vier rondes pas onder 30 zakt.
Antwoord
De eerste beurt komt bij uur = 4, de vijfde ronde; daarna ongeveer om de drie uur. Na 48 rondes zijn het 14 beurten en is er 26,64 L water over, zoals het programma zelf toonde.
Klopt dit? Het laatste getal in de tabel moet gelijk zijn aan de uitvoer van het programma. Is het niet zo, dan heb je ergens de volgorde van de regels verkeerd nagespeeld: dat is precies de fout die een trace-tabel zichtbaar maakt.
Uitleg · 27.18

while: herhalen zolang ...

18/26

Een while-lus herhaalt haar blok zolang de voorwaarde waar is. De voorwaarde wordt vóór elke ronde getest; is ze al bij de start niet waar, dan draait het blok nul keer. Je gebruikt while als je vooraf niet weet hoeveel rondes nodig zijn: hoeveel dagen tot het reservoir op het alarmniveau staat, hoeveel pogingen iemand nodig heeft.

# reservoir.py - hoeveel warme dagen tot het alarmniveau?
inhoud = 60             # L, vol voedingsreservoir
verbruik = 6            # L per warme dag
dagen = 0
while inhoud > 24:      # alarm bij 10 cm water, 24 L
    inhoud = inhoud - verbruik
    dagen = dagen + 1
print("na", dagen, "dagen:", inhoud, "L")
na 6 dagen: 24 L

Het voedingsreservoir van 60 L verliest op een warme dag tot 6 L (hoofdstuk 13); bij 10 cm water, 24 L, gaat het alarm af (hoofdstuk 11). Het Scratch-blok 'herhaal tot inhoud ≤ 24' wordt dus while inhoud > 24: de voorwaarde draait om, want Scratch zegt wanneer je stopt, Python zegt wanneer je doorgaat.

Een lus die nooit stopt

Verandert er in het blok niets aan de voorwaarde, dan stopt de lus nooit: een oneindige lus. Vergeet je inhoud = inhoud - verbruik, dan blijft de inhoud 60. Het programma lijkt te hangen; met Ctrl+C (of de stopknop van de editor) breek je het af.

while True en break

while True: loopt eindeloos, zoals de loop() van een Arduino. Met break spring je uit een lus, meestal in een if: if inhoud <= 24: break. Handig als de reden om te stoppen midden in het blok valt, maar gebruik het spaarzaam: een lus met drie break-punten is moeilijk te lezen.

inhoud = 60, dagen = 0inhoud > 24?neetoon dagen eninhoudjainhoud = inhoud − 6dagen = dagen + 1
De ruit staat bovenaan: eerst testen, dan pas het blok. De pijl terug maakt er een lus van.
Uitgewerkt voorbeeld · 27.19

Hoe lang houdt de batterij het vol zonder zon?

19/26

In een donkere winterweek levert het dak van de klimaatmodule bijna niets. De lampen gaan uit; de basis (pomp, sensoren, ventilatie, batterijbeheer) verbruikt 229,5 Wh per dag. De twee batterijen hebben samen 2457,6 Wh bruikbare energie (hoofdstuk 20). Hoeveel volle dagen houdt de module het vol?

0123456789101105001000150020002500dagen zonder zonlading in de batterij (Wh)één dag basis: 229,5 Whlading na elke ronde van de lus
Na tien rondes zit er minder dan één dag in de batterij: de voorwaarde wordt False.
Gegeven
  • bruikbare energie 2457,6 Wh (2 × 12,8 V × 120 Ah × 80 %)
  • basis 229,5 Wh per dag
  • geen zonnestroom
Gevraagd
  • het aantal volle dagen, met een while-lus
  • de energie die daarna overblijft
Oplossing
  1. 1
    Lus of formule? Met een formule: , dus 10 volle dagen. De lus doet het stap voor stap, en is makkelijk uit te breiden (een dag met wat zon, een dag met lampen).
  2. 2
    Voorwaarde. Een dag kan alleen als er nog minstens één dagverbruik in de batterij zit: while lading >= basis.
  3. 3
    Het blok. Eén dag aftrekken en één dag tellen:
    # autonomie.py - hoeveel dagen zonder zon houdt de batterij het vol?
    lading = 2457.6         # Wh bruikbaar: twee batterijen van 12,8 V en 120 Ah, 80 %
    basis = 229.5           # Wh per dag zonder lampen
    dagen = 0
    while lading >= basis:
        lading = lading - basis
        dagen = dagen + 1
    print(dagen, "volle dagen, rest", round(lading, 1), "Wh")
  4. 4
    Uitvoer:
    10 volle dagen, rest 162.6 Wh
Antwoord
10 volle dagen; daarna blijft er 162,6 Wh over, te weinig voor een elfde dag.
Klopt dit? De gehele deling geeft hetzelfde: 2457.6 // 229.5 is 10.0. Zonder round() toont Python voor de rest 162.5999999999999: tien keer een kommagetal aftrekken laat een klein foutje achter. Met de lampen aan (3269,5 Wh per dag) kom je zelfs niet door één dag.
Ontleed · 27.20

Een foutmelding lezen

20/26

Een foutmelding is geen straf maar een aanwijzing. Python zegt waar het misliep, in welke regel, en welk soort fout het is. Lees ze van onder naar boven: de laatste regel is de belangrijkste. Het volledige pad naar je bestand is hier ingekort tot de bestandsnaam.

budget.py:verbruik = 3269.51print(verbruk)2uitvoer:Traceback (most recent call last):File "budget.py", line 2, in <module>print(verbruk)^^^^^^^NameError: name 'verbruk' is not defined. Did you mean: 'verbruik'?
Een tikfout in een naam: Python stopt op regel 2 en stelt de juiste naam voor.
Wijs een nummer aan: de figuur zoomt in. Klik om vast te zetten.
  1. 1
    Traceback

    Het programma is gestart en tijdens het draaien vastgelopen. Alles wat vóór deze regel gebeurde (hier niets), is wel uitgevoerd.

  2. 2
    Waar

    Bestand en regelnummer. <module> betekent: in het hoofdprogramma, niet in een functie (hoofdstuk 28).

  3. 3
    De regel zelf

    Python herhaalt de regel waar het misliep. Vergelijk ze teken voor teken met wat je bedoelde.

  4. 4
    De plek

    De dakjes ^ onderstrepen het deel dat de fout veroorzaakte, hier de naam verbruk.

  5. 5
    Het soort fout

    NameError: Python kent deze naam niet. Een tikfout, of een variabele die nog geen waarde kreeg.

  6. 6
    De tip

    Sinds Python 3.10 stelt Python soms zelf een oplossing voor: Did you mean: 'verbruik'?

Uitleg · 27.21

Syntaxfouten: Python begrijpt de tekst niet

21/26

Bij een syntaxfout kan Python je programma niet eens lezen. Dan draait er niets, ook niet de regels vóór de fout, en er staat geen 'Traceback' boven de melding. Vier klassiekers, met de echte meldingen van Python 3.13:

De dubbelepunt ontbreekt achter de voorwaarde. Na if, elif, else, for en while komt altijd een dubbelepunt.

verbruik = 3269.5
if verbruik > 3000
    print("veel verbruik")
  File "budget.py", line 2
    if verbruik > 3000
                      ^
SyntaxError: expected ':'

Na de dubbelepunt verwacht Python een ingesprongen blok. Zet vier spaties voor print.

zon = 1750
if zon < 3269.5:
print("tekort")
  File "budget.py", line 3
    print("tekort")
    ^^^^^
IndentationError: expected an indented block after 'if' statement on line 2

Er zijn twee haakjes geopend en maar één gesloten. Het pijltje wijst het haakje aan dat nooit gesloten werd.

zon = 1400 * 1.25
print("zon:", round(zon, 1)
  File "budget.py", line 2
    print("zon:", round(zon, 1)
         ^
SyntaxError: '(' was never closed

De tekst (string) begint met een aanhalingsteken maar eindigt er niet mee.

print("verbruik per dag)
  File "budget.py", line 1
    print("verbruik per dag)
          ^
SyntaxError: unterminated string literal (detected at line 1)
De fout zit soms een regel hoger

Een vergeten haakje of aanhalingsteken merkt Python pas als het verder leest. Staat de fout op een regel die er goed uitziet, kijk dan naar de regel erboven. Een goede editor kleurt een tekst die niet sluit meteen verkeerd.

Tabs en spaties

Spring altijd in met vier spaties. De meeste editors zetten een druk op Tab om in vier spaties. Een regel die één spatie te veel inspringt, geeft IndentationError: unexpected indent.

1 Python leestSyntaxError,IndentationError: erwordt niets uitgevoerd2 Python voert uitNameError, TypeError,ValueError,ZeroDivisionError: stoptop die regel3 klaarlogische fout: geenmelding, wel eenverkeerde uitkomstvóór het draaientijdens het draaienna het draaien
Syntaxfouten stoppen alles vooraf; andere fouten stoppen op de regel waar ze gebeuren; een logische fout stopt niets.
Uitleg · 27.22

Fouten tijdens het draaien

22/26

Is de schrijfwijze in orde, dan begint Python uit te voeren. Loopt het vast, dan verschijnt een Traceback en stopt het programma op die regel. Wat ervoor stond, is uitgevoerd (en getoond). De meest voorkomende:

TypeError: een bewerking die niet past bij het type. Tekst en een getal aan elkaar plakken:

lichturen = 16
print("lichturen: " + lichturen)
Traceback (most recent call last):
  File "budget.py", line 2, in <module>
    print("lichturen: " + lichturen)
          ~~~~~~~~~~~~~~^~~~~~~~~~~
TypeError: can only concatenate str (not "int") to str

Oplossing: print("lichturen:", lichturen) of een f-string. Na input() zie je vaak een tweede soort TypeError, omdat de invoer nog tekst is:

antwoord = "25"
if antwoord > 20:
    print("warm")
Traceback (most recent call last):
  File "budget.py", line 2, in <module>
    if antwoord > 20:
       ^^^^^^^^^^^^^
TypeError: '>' not supported between instances of 'str' and 'int'

ValueError: het type klopt, de waarde niet. Tekst met een komma omzetten:

tekst = "3,5"
liter = float(tekst)
Traceback (most recent call last):
  File "budget.py", line 2, in <module>
    liter = float(tekst)
ValueError: could not convert string to float: '3,5'

ZeroDivisionError: delen door nul, bijvoorbeeld een gemiddelde over nul dagen:

dagen = 0
gemiddeld = 25 / dagen
Traceback (most recent call last):
  File "budget.py", line 2, in <module>
    gemiddeld = 25 / dagen
                ~~~^~~~~~~
ZeroDivisionError: division by zero

Deel je een kommagetal door nul, dan zegt Python float division by zero: dezelfde fout. Voorkom ze met een test vooraf: if dagen > 0:.

foutwat Python zegtwat er misliep
NameErrordeze naam ken ik niettikfout, of de variabele kreeg nog geen waarde
TypeErrordit kan niet met dit typetekst en getal gemengd, of een functie met te weinig argumenten
ValueErrorhet type klopt, de waarde niettekst die geen getal is: 'maart', '3,5', ''
ZeroDivisionErrordelen door nuleen noemer die (soms) nul is
Uitgewerkt voorbeeld · 27.23

Debuggen: een fout zonder foutmelding

23/26

Een leerling berekent de gemiddelde temperatuur uit vier metingen in de klimaatmodule. Het programma draait zonder melding, maar geeft een gemiddelde van 72,25 °C. Vind en verbeter de fout.

# gemiddelde.py - gemiddelde temperatuur uit vier metingen
t1 = 18.5
t2 = 22.0
t3 = 26.5
t4 = 21.0
gemiddelde = t1 + t2 + t3 + t4 / 4
print("gemiddelde:", gemiddelde)
gemiddelde: 72.25
Gegeven
  • vier metingen: 18,5; 22,0; 26,5 en 21,0 °C
  • de uitvoer: 72.25
Gevraagd
  • de oorzaak
  • het verbeterde programma
Oplossing
  1. 1
    Schat eerst. Een gemiddelde ligt altijd tussen de kleinste en de grootste meting: tussen 18,5 en 26,5 °C. De uitkomst 72,25 is dus fout, ook al klaagt Python niet. Dat is een logische fout.
  2. 2
    Maak tussenstappen zichtbaar. Zet tijdelijk print()-regels in het programma, vlak voor de verdachte regel:
    print("som:", t1 + t2 + t3 + t4)
    print("t4 / 4:", t4 / 4)
    som: 88.0
    t4 / 4: 5.25
    gemiddelde: 72.25
  3. 3
    Vergelijk met je verwachting. De som (88,0) klopt. Maar 72,25 is precies : alleen t4 werd door 4 gedeeld. Delen gaat vóór optellen, net zoals in de wiskunde.
  4. 4
    Verbeter en test opnieuw. Haakjes rond de som, en de hulpregels weer weg:
    gemiddelde = (t1 + t2 + t3 + t4) / 4
    gemiddelde: 22.0
Antwoord
De haakjes ontbraken: alleen t4 werd gedeeld. Met (t1 + t2 + t3 + t4) / 4 is het gemiddelde 22,0 °C.
Klopt dit? 22,0 ligt tussen 18,5 en 26,5, en ook de schatting 'rond 22' klopt. Andere manieren om zo'n fout te vinden: het programma hardop uitleggen aan iemand (of aan een badeendje: het werkt echt), en het testen met getallen waarvan je de uitkomst kent, zoals vier keer 20.
Code · 27.24

Habitat: een rekenhulp voor het energiebudget

24/26

In hoofdstuk 20 stelde je het energiebudget van de klimaatmodule op en koos je panelen en batterijen. Met een rekenhulp in Python beantwoord je snel de vragen die daarna komen: klopt het budget in een bepaalde maand? Hoeveel lichturen kan de zon alleen betalen? Hoe lang houdt de batterij de basis draaiende? Alles wat je in dit hoofdstuk leerde, zit erin: variabelen, rekenen, f-strings, if/else en twee while-lussen.

Pythonenergiebudget.py39 regelsDownload
# energiebudget.py - rekenhulp voor de klimaatmodule (gegevens uit hoofdstuk 20) # 1. verbruik per dag in Wh: vermogen (W) maal uren per daglampen = 190 * 16                  # twee groeilampen van 95 W, 16 lichturenpomp = 12 * 4                      # 10 minuten per uur is 4 uur per dagsensoren = 3.0 * 24                # microcontroller, sensoren en dataloggerventilatie = 5 * 16 + 2 * 8        # 5 W overdag, 2 W 's nachtsco2_klep = 6 * 0.25bms = 0.5 * 24                     # laadregelaar en batterijbeheerbasis = pomp + sensoren + ventilatie + co2_klep + bmsverbruik = basis + lampen # 2. zonnestroom in de gekozen maandmaand = "december"                 # in het echt: maand = input("Maand? ")wh_per_wp = 1.25                   # PVGIS: Wh per Wp per dag in die maandpiek = 4 * 350                     # vier panelen van 350 Wpzon = piek * wh_per_wpsaldo = zon - verbruik print(f"verbruik: {verbruik:.1f} Wh per dag, waarvan {lampen} Wh voor de lampen")print(f"zonnestroom in {maand}: {zon:.0f} Wh per dag")if saldo >= 0:    print(f"overschot: {saldo:.0f} Wh per dag")else:    print(f"tekort: {-saldo:.0f} Wh per dag") # 3. hoeveel lichturen kan de zon alleen betalen?lichturen = 16while lichturen > 0 and basis + 190 * lichturen > zon:    lichturen = lichturen - 1print("lichturen op zonnestroom:", lichturen, "van de 16") # 4. hoeveel dagen houdt de batterij de basis draaiende zonder zon?lading = 2 * 0.80 * 120 * 12.8     # twee LiFePO4-batterijen, 80 % bruikbaar (Wh)dagen = 0while lading >= basis:    lading = lading - basis    dagen = dagen + 1print(f"batterij: {dagen} dagen zonder zon (en zonder lampen)")
024681012141618lichturen op zonnestroom per dag9141616161616161616118janfebmrtaprmeijunjulaugsepoktnovdec
Het programma twaalf keer gedraaid, één keer per maand: van november tot februari betaalt de zon geen 16 lichturen.

Uitvoer voor december:

verbruik: 3269.5 Wh per dag, waarvan 3040 Wh voor de lampen
zonnestroom in december: 1750 Wh per dag
tekort: 1520 Wh per dag
lichturen op zonnestroom: 8 van de 16
batterij: 10 dagen zonder zon (en zonder lampen)

En voor maart (enkel maand en wh_per_wp aangepast, 2,99 Wh per Wp):

verbruik: 3269.5 Wh per dag, waarvan 3040 Wh voor de lampen
zonnestroom in maart: 4186 Wh per dag
overschot: 916 Wh per dag
lichturen op zonnestroom: 16 van de 16
batterij: 10 dagen zonder zon (en zonder lampen)

De lichturen-lus begint bij 16 en trekt er één af zolang basis plus lampen meer vragen dan de zon levert. In december blijven er 8 over. Hoofdstuk 20 kwam op ongeveer 7,5 uur, omdat daar ook het verlies in de batterij meetelde: de lampen branden deels 's avonds, op stroom die eerst in de batterij moest. De rekenhulp is dus een snelle eerste schatting, geen vervanging van het uurmodel.

Waarom geen lijst met twaalf maanden?

Om een andere maand te kiezen, pas je nu twee regels aan. Met twaalf elif-takken zou het programma de waarde zelf kunnen kiezen, maar dat wordt lang en foutgevoelig. In hoofdstuk 28 zet je de twaalf PVGIS-waarden in één lijst en rekent een functie elke maand in één lus uit.

Naslag · 27.25

Python in één oogopslag

25/26

De bouwstenen uit dit hoofdstuk, met hun blokken uit Fundamental en hun vorm in C++, zoals je ze in hoofdstuk 29 tegenkomt.

ScratchPythonC++ (Arduino, hoofdstuk 29)
maak [x] (5)x = 5int x = 5;
verander [x] met (1)x = x + 1 of x += 1x = x + 1; of x++;
herhaal (10)for i in range(10):for (int i = 0; i < 10; i++) { ... }
herhaal tot <v>while not v:while (!v) { ... }
herhaal (eindeloos)while True:void loop() { ... }
als <v> dan ... andersif v: ... else:if (v) { ... } else { ... }
zeg (x)print(x)Serial.println(x);
vraag [...] en wachtinput("...")(tekst lezen via Serial)
<x = 5>x == 5x == 5
en, of, nietand, or, not&&, ||, !
tekenbewerkingvoorbeelduitkomstopmerking
+optellen17 + 522
-aftrekken17 - 512
*vermenigvuldigen17 * 585geen × of ·
/delen17 / 53.4altijd een float, ook bij 10 / 5
//gehele deling17 // 53afgerond naar beneden
%rest (modulo)17 % 52wat overblijft na de gehele deling
**macht2 ** 101024niet ^ (dat is iets anders in Python)
waardef-stringresultaatbetekenis
x = 3269.5f"{x:.2f}"'3269.50'2 decimalen
x = 3269.5f"{x:.0f}"'3270'afgerond op een geheel getal
x = 3269.5f"{x:10.1f}"'    3269.5'10 tekens breed, 1 decimaal (rechts uitgelijnd)
x = 916.5f"{x:+.1f}"'+916.5'altijd een teken, ook +
x = 0.535f"{x:.0%}"'54%'als procent (maal 100)
s = "pomp"f"{s:<10}|"'pomp      |'10 tekens breed, links uitgelijnd
n = 48f"{n:>5}"'   48'5 tekens breed, rechts uitgelijnd
n = 48f"{n:05d}"'00048'aanvullen met nullen
meldingtypische oorzaakwat je doet
SyntaxError: expected ':'dubbelepunt vergeten na if, elif, else, for, whiledubbelepunt toevoegen
SyntaxError: '(' was never closedhaakje niet geslotenhaakjes tellen; de fout zit vaak op de regel ervoor
SyntaxError: unterminated string literalaanhalingsteken vergetentekst afsluiten met hetzelfde teken
IndentationErrorblok niet (of te veel) ingesprongenvier spaties per niveau, geen tabs mengen
NameError: name '...' is not definedtikfout in een naam, of variabele nog niet gemaaktnaam nakijken (hoofdletters tellen)
TypeError: can only concatenate str ...tekst + getalf-string gebruiken, of str()
TypeError: '>' not supported ...tekst vergelijken met een getal (vaak na input())eerst int() of float()
ValueError: could not convert ...tekst die geen getal is, of een decimale komma.replace(",", ".") of invoer controleren
ZeroDivisionErrordelen door nuleerst testen of de noemer nul is
Het geheel · 27.26

Waar Python vandaan komt en waar het heen gaat

26/26

Dit hoofdstuk is de brug tussen de blokken van Fundamental en alles wat daarna met code gebeurt. De denkstappen zijn dezelfde gebleven (decompositie, een algoritme, naspelen, debuggen), alleen de schrijfwijze is nieuw. Programmeren raakt bijna elke leerlijn: je rekent energiebudgetten uit (E), simuleert een proces (W), verwerkt metingen (O, A) en stuurt een regeling aan (R).

Algoritme, stroomdiagram en trace-tabel: dezelfde denkstappen, nu in tekst.

De blokken die je hier naar Python vertaalde, en de kas-simulatie.

Een drempel en een aan/uit-regeling: if/else op een microcontroller.

Het energiebudget waarvoor je de rekenhulp schreef.

Het tweetallig stelsel verklaart waarom 0,1 + 0,2 niet precies 0,3 is.

Functies, lijsten en woordenboeken, CSV-bestanden en grafieken: de volgende stap.

Dezelfde structuren in C++ op de Arduino: accolades in plaats van inspringen.

Python leest de metingen die de microcontroller doorstuurt.

Een beslisboom is een reeks if-else-vragen die de computer zelf leert.

Hoe snel een lus is, en waarom sommige algoritmen te traag worden.

Lussen die een differentiaalvergelijking stap voor stap uitrekenen.

HabitatDe klimaatmodule heeft nu een rekenhulp voor haar energiebudget: ze toont per maand het saldo, het aantal lichturen dat de zon alleen kan betalen (december 8, januari 9, november 11, februari 14, de rest van het jaar 16) en de autonomie van de batterij voor de basis (10 dagen). In opdracht 27.14 breid je ze uit; in hoofdstuk 28 wordt ze korter met lijsten en functies.
Samenvatting

In het kort

Begrippen

Wat je nu kent

Python
Een programmeertaal die je leest bijna als Engelse tekst; een interpreter voert het programma regel per regel uit.
interpreter
Het programma dat Python-code leest en meteen uitvoert (tegenover een compiler, die eerst alles vertaalt).
interactieve shell
Het venster met de prompt >>> waarin je één regel Python typt en meteen de uitkomst ziet.
toekenning
Een regel als vocht = 50: de naam links wijst voortaan naar de waarde rechts.
type
De soort van een waarde: int (geheel getal), float (kommagetal), str (tekst) of bool (True of False).
f-string
Tekst met f ervoor waarin waarden tussen accolades komen, met een opmaak zoals {x:.1f}.
voorwaarde
Een uitdrukking die True of False oplevert, zoals vocht < 30; ze stuurt if en while.
inspringen
Spaties aan het begin van een regel (vier per niveau): ze bepalen welke regels bij een if, for of while horen.
for-lus
Een lus die een vast aantal keer loopt, of één keer voor elke waarde uit een reeks, zoals range(48).
while-lus
Een lus die herhaalt zolang een voorwaarde waar is; de voorwaarde wordt vóór elke ronde getest.
trace-tabel
Een tabel waarin je de waarden van de variabelen na elke stap noteert, om een programma na te spelen.
traceback
De foutmelding van Python: waar het misliep (bestand, regel) en welk soort fout, onderaan het belangrijkst.
syntaxfout
Een fout in de schrijfwijze: Python begrijpt de tekst niet en voert niets uit.
logische fout
Het programma draait zonder melding, maar rekent iets anders uit dan je bedoelde.
Aan de slag in het werkboek17 opdrachten, van oefenen tot uitdagen