Van blokken naar tekst: variabelen, rekenen, keuzes, lussen en foutmeldingen die je leert lezen
Uitgewerkte oplossingen bij de 17 opdrachten van het werkboek. Voor de leerkracht, en voor wie zichzelf wil verbeteren nadat hij het eerst zelf probeerde.
range(10, 0, -1) geeft 10 tot en met 1; de stopwaarde 0 doet niet mee.
d
Wat verander je aan je while-versie zodat ook 0 getoond wordt?
while tijd >= 0:. Met != -1 kan het ook, maar >= is veiliger: als de stap ooit groter wordt, schiet != voorbij.
27.2
Welk type, welke waarde?
Oefenen3Begrijpen12 min
Schrijf voor elke uitdrukking op wat Python als uitkomst geeft en van welk type ze is. Controleer daarna in de shell.
a
Vul de tabel in.
uitdrukking
type
waarde
7 / 2
float
3.5
7 // 2
int
3
7 % 2
int
1
2 ** 3
int
8
3.0 * 2
float
6.0
"7" + "2"
str
'72'
"7" * 3
str
'777'
7 > 2
bool
True
int("7") + 2
int
9
float(7)
float
7.0
round(2.567, 1)
float
2.6
10 / 5
float
2.0
b
Bij welke twee uitdrukkingen is het type anders dan je op het eerste gezicht zou denken? Leg uit.
10 / 5 geeft 2.0, een float: gewoon delen geeft altijd een float, ook als de deling opgaat. En "7" + "2" geeft de tekst '72', geen 9: tussen aanhalingstekens is 7 tekst. (Ook float(7) is een float, 7.0, maar daar vraag je er zelf om.)
27.3
Rekenen met // en %
Oefenen3Rekenen12 min
Schrijf telkens de Python-uitdrukking(en) en de uitkomst.
a
De groeilampen branden 1000 minuten. Hoeveel uur en minuten is dat?
1000 // 60 = 16 uur en 1000 % 60 = 40 minuten: 16 h 40 min.
b
De pomp van de meetkas draait 225 s per dag. Hoeveel minuten en seconden?
225 // 60 = 3 min en 225 % 60 = 45 s.
c
48 plantplaatsen gaan in goten van 7 plaatsen. Hoeveel goten zijn helemaal vol, en hoeveel plaatsen blijven over?
48 // 7 = 6 volle goten, 48 % 7 = 6 plaatsen over (in een zevende goot).
d
De logger bewaart om de 5 minuten een meting, genummerd vanaf 0 om middernacht. Om hoe laat valt meting 170?
170 × 5 = 850 minuten; 850 // 60 = 14 en 850 % 60 = 10: om 14:10.
e
Schrijf een voorwaarde die True is als het getal n even is.
n % 2 == 0: de rest bij delen door 2 is nul.
27.4
Voorspel de uitvoer
Oefenen4Analyseren12 min
Voorspel wat dit programma toont, zonder het te draaien. Houd de waarde van elke variabele bij in de kantlijn.
a wordt 6; b is eerst 10 (5 * 2, met de oude a), c = 10 / 4 = 2.5, en daarna b = 10 // 3 = 3. a + b * 2 = 6 + 6 = 12. "3" * 6 herhaalt de tekst zes keer.
b
Welke waarde heeft b op het einde, en waarom is dat geen 3.33?
b = 3: // is de gehele deling, die de decimalen weglaat. Met / was het 3.3333333333333335 geweest.
27.5
Netjes tonen met f-strings
Oefenen4Programmeren15 min
Gegeven: verbruik = 3269.5 (Wh per dag) en zon = 1750.0 (Wh per dag in december).
a
Schrijf twee print()-regels die precies dit tonen:
verbruik: 3,27 kWh per dag
zonnestroom: 1750 Wh (54 % van het verbruik)
verbruik=3269.5zon=1750.0tekst=f"{verbruik/1000:.2f}".replace(".",",")print(f"verbruik: {tekst} kWh per dag")print(f"zonnestroom: {zon:.0f} Wh ({100*zon/verbruik:.0f} % van het verbruik)")
Let op de spatie vóór het procentteken: daarom {100 * zon / verbruik:.0f} % en niet {zon / verbruik:.0%} (dat geeft 54% zonder spatie).
b
Waarom mag je met de variabele die '3,27' bevat niet meer verder rekenen?
Het is tekst (str) geworden, met een komma die Python niet als getal herkent: tekst * 2 geeft '3,273,27', en float() geeft een ValueError. Omzetten naar een komma doe je dus pas bij het tonen.
27.6
Lees de foutmelding
Oefenen4Begrijpen15 min
Vier leerlingen krijgen een foutmelding (Python 3.13). Zeg telkens welk soort fout het is, op welke regel, wat er fout is, en hoe je het verbetert.
a
A
print("verbruik per dag)
File "budget.py", line 1
print("verbruik per dag)
^
SyntaxError: unterminated string literal (detected at line 1)
SyntaxError op regel 1: de tekst begint met een aanhalingsteken maar sluit niet. Verbeterd: print("verbruik per dag"). Er draait niets, er staat geen Traceback boven.
b
B
zon=1400*1.25print("zon:",round(zon,1)
File "budget.py", line 2
print("zon:", round(zon, 1)
^
SyntaxError: '(' was never closed
SyntaxError op regel 2: het haakje van print( wordt nooit gesloten (dat van round wel). Verbeterd: print("zon:", round(zon, 1)).
c
C
maand=int("maart")
Traceback (most recent call last):
File "budget.py", line 1, in <module>
maand = int("maart")
ValueError: invalid literal for int() with base 10: 'maart'
ValueError op regel 1: int() kan alleen tekst met cijfers omzetten, 'maart' is geen getal. Gebruik maand = 3, of vraag een getal van 1 tot 12.
d
D
antwoord="25"ifantwoord>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'
TypeError op regel 2: '25' is tekst (zoals alles uit input()) en tekst kan je niet met een getal vergelijken. Verbeterd: if int(antwoord) > 20:, of meteen antwoord = int(...).
Toepassen
Toepassen
meerdere stappen, in een context
27.7
Trace-tabel: algen in het reservoir
Toepassen4Rekenen15 min
In een doorzichtig reservoir verdubbelen de algen elke dag (hoofdstuk 5). Het alarm gaat af boven 500 000 cellen per mL. Het programma zoekt na hoeveel dagen dat gebeurt.
algen=2000# cellen per mLdagen=0whilealgen<=500000:algen=algen*2dagen=dagen+1print(dagen,algen)
a
Speel het programma na. Vul een rij in voor elke test van de voorwaarde.
dagen
algen
algen <= 500000?
0
2000
True
1
4000
True
2
8000
True
3
16000
True
4
32000
True
5
64000
True
6
128000
True
7
256000
True
8
512000
False: stop
b
Wat toont het programma? Hoeveel keer wordt de voorwaarde getest, en hoeveel keer draait het blok?
Uitvoer: 8 512000. De voorwaarde wordt 9 keer getest, het blok draait 8 keer: de laatste test is False en stopt de lus.
c
Hoofdstuk 5 rekende met logaritmen 7,97 dagen uit. Waarom geeft de lus 8?
De lus telt alleen hele dagen: na 7 dagen zijn het er 256 000, na 8 dagen 512 000. Het alarm gaat dus af in de loop van de achtste dag (na 7,97 dagen).
27.8
Van code naar stroomdiagram
Toepassen4Tekenen20 min
Neem het programma kas_simulatie.py uit het handboek (de simulatie van de meetkas).
a
Teken het stroomdiagram met de symbolen uit F22. Een stroomdiagram kent geen for: gebruik een teller uur en een ruit.
De for-lus wordt: uur = 0 vóór de lus, de ruit 'uur < 48?' bovenaan, en uur = uur + 1 onderaan, met de pijl terug naar de ruit.
b
Waar in je stroomdiagram zit het inspringen van de code?
Het inspringen is de lus van pijlen: wat binnen de pijl terug ligt, hoort bij de for; wat tussen de ja-uitgang van 'vocht < 30?' en het samenkomen ligt, hoort bij de if.
27.9
De volgorde van elif
Toepassen5Analyseren15 min
Een leerling schrijft een klimaatwaarschuwing voor de klimaatmodule.
temp=31iftemp>18:print("goed")eliftemp>26:print("warm: ventileren")eliftemp>30:print("te heet: dak open en lampen dimmen")else:print("te koud")
a
Wat toont het programma voor temp = 31, 22, 27 en 15?
31: goed; 22: goed; 27: goed; 15: te koud.
b
Waarom verschijnt 'warm' of 'te heet' nooit?
Elke temperatuur boven 26 is ook boven 18. De eerste voorwaarde is dan al waar, dus de elif-takken worden nooit meer getest.
c
Herschrijf de keuze zodat elke tak werkt.
temp=31iftemp>30:print("te heet: dak open en lampen dimmen")eliftemp>26:print("warm: ventileren")eliftemp>18:print("goed")else:print("te koud")
Nu: 31: te heet: dak open en lampen dimmen; 22: goed; 27: warm: ventileren; 15: te koud. De strengste voorwaarde staat bovenaan.
27.10
Een EC-meter met advies
Toepassen5Programmeren20 min
De EC van de voedingsoplossing moet tussen 1,2 en 1,8 mS/cm liggen; de streefwaarde is 1,4 (hoofdstuk 13). Een gebruiker typt de gemeten EC, soms met een komma.
a
Schrijf een programma dat de invoer omzet (ook met een komma), advies geeft (te laag, te hoog of in orde) en de afwijking van 1,4 in procent toont, met een teken. Zet de invoer voorlopig in een variabele.
tekst="1,15"# in het echt: tekst = input("EC (mS/cm)? ")ec=float(tekst.replace(",","."))afwijking=(ec-1.4)/1.4*100ifec<1.2:print("te laag: stamoplossing A en B bijdoseren")elifec>1.8:print("te hoog: aanlengen met regenwater")else:print("in orde")print(f"afwijking van 1,4 mS/cm: {afwijking:+.0f} %")
b
Test met 1,15; 1,2; 1,4 en 1,9. Welke test is een grensgeval, en wat moet daar uitkomen?
invoer
uitvoer
1,15
te laag: stamoplossing A en B bijdoseren afwijking van 1,4 mS/cm: -18 %
1,2
in orde afwijking van 1,4 mS/cm: -14 %
1,4
in orde afwijking van 1,4 mS/cm: +0 %
1,9
te hoog: aanlengen met regenwater afwijking van 1,4 mS/cm: +36 %
1,2 is het grensgeval: 'onder 1,2' is niet waar voor 1,2 zelf, dus 'in orde'.
27.11
Waar of niet waar?
Toepassen5Begrijpen12 min
In de klimaatmodule gelden op dit moment deze waarden:
temp=27.5vocht=82deur_open=Falsenacht=True
a
Geef de uitkomst (True of False) van elke uitdrukking.
uitdrukking
uitkomst
temp > 26 and vocht > 80
True
temp > 30 or vocht > 80
True
not deur_open and temp > 26
True
nacht and not vocht < 85
False
20 <= temp <= 26
False
temp > 30 or nacht and vocht > 90
False
De laatste: and gaat voor or, dus temp > 30 or (nacht and vocht > 90) = False or False.
b
Schrijf één voorwaarde voor: de ventilator gaat aan als het warmer is dan 26 °C of vochtiger dan 85 %, maar nooit als de deur openstaat.
(temp > 26 or vocht > 85) and not deur_open. Zonder de haakjes zou vocht > 85 and not deur_open samen genomen worden, en ging de ventilator bij warmte ook aan met de deur open.
27.12
Het dakraam met hysterese
Toepassen6Programmeren25 min
Het dakraam van de meetkas gaat open boven 28 °C en pas weer dicht onder 25 °C (F25). Die twee drempels (hysterese) voorkomen dat het raam bij elke kleine schommeling op en neer gaat. De sensor meet achtereenvolgens: 27; 28,5; 27,9; 28,2; 26; 24,5; 25,5 en 24 °C.
a
Schrijf een programma met een variabele raam_open (True of False) dat de metingen overloopt, het raam opent of sluit, elke schakeling toont en ze telt. Een for-lus kan over een reeks waarden tussen haakjes lopen.
28.5 graden: raam open
24.5 graden: raam dicht
schakelingen: 2
b
Hoeveel keer schakelt het raam? Hoeveel keer zou het schakelen met één drempel van 28 °C (open erboven, dicht eronder)?
Met hysterese 2 keer. Met één drempel: schakelingen: 4 (open bij 28,5, dicht bij 27,9, open bij 28,2, dicht bij 26).
c
Waarom staat er and not raam_open in de voorwaarde om te openen?
Zonder die test telt het programma bij 28,2 een tweede 'open' terwijl het raam al open is. De toestand onthouden en alleen bij een verandering schakelen, is de kern van een regeling met hysterese (hoofdstuk 31).
27.13
Foutenjacht: vier fouten in één programma
Toepassen6Analyseren20 min
Dit programma moet het verbruik van de pomp van de klimaatmodule tonen (12 W, 10 minuten per uur). Er zitten vier fouten in.
# pomp.py - energie van de pomp van de klimaatmodulevermogen=12# Wminuten=10# per uurenergie=vermogen*minuten/60ifenergie>1print("de pomp verbruikt meer dan 1 Wh per uur")print("energie per uur: "+energie+" Wh")per_dag=energie*24print(f"per dag: {per_dg:.0f} Wh")
a
Python toont je de fouten niet alle vier tegelijk. Geef ze in de volgorde waarin je ze krijgt, met het soort fout en de regel.
1. SyntaxError op regel 5 (dubbelepunt vergeten). 2. Na verbeteren: IndentationError op regel 6 (print niet ingesprongen). 3. Daarna: TypeError op regel 7 (tekst + float). 4. Daarna: NameError op regel 9 (per_dg in plaats van per_dag). De echte meldingen, na elke verbetering opnieuw gedraaid:
File "pomp.py", line 5
if energie > 1
^
SyntaxError: expected ':'
File "pomp.py", line 6
print("de pomp verbruikt meer dan 1 Wh per uur")
^^^^^
IndentationError: expected an indented block after 'if' statement on line 5
de pomp verbruikt meer dan 1 Wh per uur
Traceback (most recent call last):
File "pomp.py", line 7, in <module>
print("energie per uur: " + energie + " Wh")
~~~~~~~~~~~~~~~~~~~~^~~~~~~~~
TypeError: can only concatenate str (not "float") to str
de pomp verbruikt meer dan 1 Wh per uur
energie per uur: 2.0 Wh
Traceback (most recent call last):
File "pomp.py", line 9, in <module>
print(f"per dag: {per_dg:.0f} Wh")
^^^^^^
NameError: name 'per_dg' is not defined. Did you mean: 'per_dag'?
b
Waarom verschijnt de eerste regel uitvoer al bij de derde fout, maar niet bij de eerste twee?
Syntaxfouten en inspringfouten ziet Python bij het lezen, vóór er iets draait. De TypeError gebeurt pas tijdens het uitvoeren van regel 7: regel 6 is dan al uitgevoerd.
c
Schrijf het verbeterde programma. Wat toont het?
# pomp.py - energie van de pomp van de klimaatmodulevermogen=12# Wminuten=10# per uurenergie=vermogen*minuten/60ifenergie>1:print("de pomp verbruikt meer dan 1 Wh per uur")print(f"energie per uur: {energie} Wh")per_dag=energie*24print(f"per dag: {per_dag:.0f} Wh")
de pomp verbruikt meer dan 1 Wh per uur
energie per uur: 2.0 Wh
per dag: 48 Wh
48 Wh per dag: hetzelfde als in het budget van hoofdstuk 20.
Uitdagen
Uitdagen
transfer, open problemen, leerlijnen combineren
27.14
Habitat: de rekenhulp uitbreiden
Uitdagen6Habitat45 min
Vertrek van energiebudget.py uit het handboek. De klimaatmodule wil weten wat er in de wintermaanden nodig is om toch 16 lichturen op zonnestroom te halen. PVGIS (Wh per Wp per dag): januari 1,41; februari 2,11; november 1,66; december 1,25. Een paneel van 350 Wp meet 1,65 × 1,00 m.
a
Schrijf de twee regels die de maand en de PVGIS-waarde echt met input() vragen, zodat een gebruiker ook '1,25' met een komma kan typen.
maand=input("Maand? ")wh_per_wp=float(input("PVGIS (Wh per Wp per dag)? ").replace(",","."))
b
Voeg een while-lus toe die zoekt hoeveel panelen van 350 Wp nodig zijn om het volledige verbruik (3269,5 Wh per dag) op zonnestroom te halen.
verbruik=3269.5# Wh per dag, met 16 lichturenwh_per_wp=1.25# decemberpanelen=4whilepanelen*350*wh_per_wp<verbruik:panelen=panelen+1print("december:",panelen,"panelen,",round(panelen*1.65,1),"m2")
Is dat een goed idee? Vergelijk met de vier panelen die er liggen (hoofdstuk 20) en noem een alternatief.
Dubbel zoveel panelen voor twee à drie donkere maanden: in de zomer lever je dan een groot overschot dat niemand gebruikt, en op het platte dak is er plaats voor twee rijen (hoofdstuk 20). Betere alternatieven: minder lichturen in de winter (de lampen zijn de afschakelbare last), stroom van het station, of lampen die dimmen als er daglicht is (hoofdstuk 25).
Zo wordt dit beoordeeld
Invoer
input() met omzetting en vervangen van de komma; de maand als tekst of als getal.
Lus
Juiste voorwaarde (stopt bij het eerste aantal dat volstaat), beginwaarde vóór de lus, geen oneindige lus.
Resultaten
Tabel volledig en getest tegen een schatting (verbruik / (350 × PVGIS), naar boven afgerond).
Besluit
Afweging met ruimte op het dak, kosten en de zomer (dan grote overschotten); een alternatief benoemd.
27.15
Het vermoeden van Collatz
Uitdagen7Programmeren30 min
Neem een positief geheel getal n. Is het even, deel het door 2; is het oneven, neem 3n + 1. Herhaal. Het vermoeden van Collatz (1937) zegt dat je altijd bij 1 uitkomt. Niemand heeft het ooit bewezen, en niemand heeft een tegenvoorbeeld gevonden. Voorbeeld: 6, 3, 10, 5, 16, 8, 4, 2, 1 (8 stappen).
a
Schrijf een programma dat voor een startwaarde het aantal stappen tot 1 telt en de grootste waarde onderweg bijhoudt. Test het met 6.
De som is 0.9999999999999999, dus som == 1 is False; na afronden of met een kleine marge klopt het wel.
b
Zoek twee sommen met kommagetallen die wél exact kloppen en twee die niet kloppen. Welk patroon zie je? (Denk aan het tweetallig stelsel, hoofdstuk 25.)
0,5 + 0,25 = 0,75 klopt exact, net als 0,125 + 0,375: dat zijn breuken met 2, 4, 8, ... in de noemer, die in het tweetallig stelsel eindig zijn. 0,1 + 0,2 en 0,1 × 3 kloppen niet: 1/10 is in het tweetallig stelsel een oneindig repeterende breuk, zoals 1/3 in het tientallig.
c
Een programma test if ph == 5.8: om te weten of de pH precies op de streefwaarde zit. Waarom is dat een slecht idee, en hoe doe je het beter?
Een gemeten pH is bijna nooit precies 5.8, en een berekende al helemaal niet. Test met een marge: if abs(ph - 5.8) < 0.05:, of test een bereik: 5.5 <= ph <= 6.5. De marge kies je uit de meetonzekerheid (hoofdstuk 1).
Zo wordt dit beoordeeld
Voorspelling
Eerst voorspeld, dan gecontroleerd; afwijkingen benoemd.
Patroon
Breuken met een macht van 2 in de noemer (0,5; 0,25; 0,75) zijn exact, andere niet.
Toepassing
Vergelijken met een marge of afronden, gemotiveerd.
27.17
Debat: blokken of tekst?
Uitdagen5Argumenteren20 min
Een leraar stelt voor om de klimaatmodule in blokken te blijven programmeren (mBlock voor de Arduino), 'want dan maakt niemand typfouten'. Een leerling vindt dat Python en C++ beter zijn.
a
Geef twee sterke argumenten voor blokken en twee voor tekst, telkens met een concreet voorbeeld uit dit hoofdstuk.
Blokken: geen syntaxfouten mogelijk (een blok dat niet past, klikt niet vast), en de structuur is meteen zichtbaar (de mond van een C-blok). Tekst: een lang programma blijft overzichtelijk en je kan het kopiëren, zoeken en vergelijken (de rekenhulp van 40 regels zou een enorme blokkentoren zijn), en je hebt bibliotheken (math, later csv en matplotlib) die in blokken ontbreken.
b
Voor welk soort programma of welke gebruiker zou jij blokken kiezen, en voor welk tekst? Motiveer.
Blokken voor een eerste kennismaking, een korte demonstratie of een bezoeker die iets wil aanpassen; tekst voor alles wat groeit, hergebruikt of door meerdere mensen onderhouden wordt, zoals de sturing en de data-analyse van de klimaatmodule. Een goed antwoord weegt ook de gebruiker af, niet alleen de taal.