Handboek · hoofdstuk 28Functies, lijsten en data in Python
Eigen functies, lijsten en woordenboeken, en een week meetdata van de klimaatmodule tot een besluit
Een datalogger schrijft elke paar minuten een regel met metingen. Na een week zijn dat er honderden: te veel om met de hand te bekijken, maar voor Python een paar regels code. In dit hoofdstuk leer je je eigen functies schrijven, veel waarden bewaren in lijsten en woordenboeken, een CSV-bestand inlezen en er gemiddelden, minima, maxima en grafieken uit halen. Aan het eind analyseer je een week in de klimaatmodule.

- Je kan een functie schrijven met parameters, een standaardwaarde, een returnwaarde en een docstring, en ze aanroepen.
- Je kan het verschil tussen print en return uitleggen en een functie testen met gekozen invoer.
- Je kan lijsten maken, indexeren (ook met een negatieve index), in stukken knippen en aanvullen met append.
- Je kan met len, sum, min, max en sorted rekenen op een lijst, en een gemiddelde en een maximum ook zelf programmeren.
- Je kan over een lijst lopen om op te hopen, te tellen, te filteren en een nieuwe lijst te maken, ook met zip.
- Je kan een woordenboek gebruiken om waarden op te zoeken en om metingen per groep te verzamelen.
- Je kan een CSV-bestand inlezen met de csv-module, de teksten omzetten en ontbrekende waarden opvangen.
- Je kan een week meetdata per dag samenvatten en er een onderbouwd besluit uit trekken.
- Je kan met matplotlib een lijngrafiek en een staafdiagram maken met asopschriften, eenheden en een legende.
Vijf landen te weinig
In 2010 publiceerden twee bekende Amerikaanse economen een studie over staatsschulden. Hun besluit: landen met een schuld boven 90 % van hun jaarlijkse productie groeiden gemiddeld niet meer, zelfs licht achteruit. Politici overal ter wereld haalden het cijfer aan.
In 2013 kreeg Thomas Herndon, een student aan de universiteit van Massachusetts, als oefening de opdracht om een bekende studie opnieuw uit te rekenen. Hij koos deze, kwam niet op dezelfde getallen uit, en vroeg het rekenblad van de auteurs op. Daarin vond hij onder meer een formule voor een gemiddelde die over een te kort bereik liep: vijf landen telden niet mee, Australië, Oostenrijk, België, Canada en Denemarken. Samen met andere keuzes in de analyse (welke jaren meetelden, hoe landen gewogen werden) werd de gemiddelde groei bij een hoge schuld ongeveer +2,2 % per jaar in plaats van −0,1 %. De auteurs erkenden de rekenbladfout, maar verdedigden hun besluit.
Een rekenblad is niet slecht, maar een formule in cel F67 zie je niet staan. In een programma staat elke stap zichtbaar als tekst, test je met len() hoeveel waarden er echt meetellen, en kan iemand anders dezelfde berekening op dezelfde data opnieuw draaien. Dat heet reproduceerbaar werken, en het is de kern van goed onderzoek (hoofdstuk 2).
De klimaatmodule meet temperatuur, vochtigheid, verbruik en zonnestroom. Die metingen zijn alleen iets waard als je ze betrouwbaar samenvat: per dag, per dagdeel, met gemiddelden en grafieken. Dat doe je hier met functies, lijsten en woordenboeken, en straks met de echte datalogger van hoofdstuk 30.

Wat je al kan, en waar dit hoofdstuk naartoe gaat
| wat je al kan | wat er nu bijkomt |
|---|---|
| variabelen, if, for en while; ingebouwde functies als print(), round() en len() (hoofdstuk 27) | zelf functies schrijven, met parameters en een returnwaarde |
| een rij waarden tussen haakjes in een for-lus (hoofdstuk 27) | lijsten die je aanvult, doorzoekt, sorteert en in stukken knipt; woordenboeken |
| gemiddelde, bereik en uitschieters (hoofdstuk 1); een rekenblad en een trendlijn (hoofdstuk 3) | dezelfde statistiek in code, voor honderden metingen in één keer |
| een grafiek met assen, grootheid, eenheid en schaal (F4) | grafieken laten tekenen met matplotlib |
In hoofdstuk 27 schreef je programma's van boven naar onder, met een variabele voor elke waarde. Voor een week meetdata werkt dat niet meer: 56 rijen met elk vijf waarden zijn 280 getallen. Drie nieuwe bouwstenen lossen dat op. Een functie geeft een berekening een naam, zodat je ze telkens opnieuw kan gebruiken. Een lijst bewaart veel waarden onder één naam. Een woordenboek koppelt een naam (een sleutel) aan een waarde. Samen met de csv-module om bestanden te lezen en matplotlib om te tekenen, heb je alles om van meetdata een besluit te maken.
Functies: een berekening met een naam
Je gebruikte al veel functies: print(), round(), len(). Een eigen functie maak je met def:
def energie(vermogen, uren):
"""Energie in Wh van een toestel met dit vermogen (W) dat zoveel uren aanstaat."""
return vermogen * urenDe eerste regel is de kop: het woord def, de naam, de parameters tussen haakjes en een dubbelepunt. Daaronder het ingesprongen lichaam. De tekst tussen drie aanhalingstekens is de docstring: wat de functie doet, met eenheden. Met return geeft de functie een waarde terug en stopt ze.
Een def voert nog niets uit; het maakt de functie alleen klaar. Pas bij een aanroep zoals energie(190, 16) draait het lichaam: de argumenten 190 en 16 worden de waarden van de parameters vermogen en uren, en de aanroep zelf krijgt de waarde 3040.
Als je dezelfde berekening twee keer typt, of als een stuk code een duidelijke eigen taak heeft (een ADC-waarde omrekenen, een gemiddelde nemen). Een goede functie doet één ding, heeft een naam die zegt wat (een werkwoord of wat ze teruggeeft), en een docstring. Test ze met invoer waarvan je de uitkomst kent.
Je eerste eigen functies
Twee functies voor het energiebudget: energie() rekent, komma() maakt van een getal een tekst met een decimale komma (de truc uit hoofdstuk 27, nu met een naam). {x:.{decimalen}f} is een f-string in een f-string: het aantal decimalen komt zelf uit een variabele.
# functies.py - eigen functies met parameters en een returnwaardedef energie(vermogen, uren): """Energie in Wh van een toestel met dit vermogen (W) dat zoveel uren aanstaat.""" return vermogen * uren def komma(x, decimalen=1): """Getal als tekst met een decimale komma: komma(3.14159, 2) geeft '3,14'.""" return f"{x:.{decimalen}f}".replace(".", ",") lampen = energie(190, 16)pomp = energie(12, 4)print(lampen, pomp)print("samen:", komma((lampen + pomp) / 1000, 2), "kWh")print("pomp per uur:", komma(energie(12, 10 / 60)), "Wh")print(energie.__doc__)Uitvoer:
3040 48 samen: 3,09 kWh pomp per uur: 2,0 Wh Energie in Wh van een toestel met dit vermogen (W) dat zoveel uren aanstaat.
Een functie mag een andere functie aanroepen, en een aanroep mag in een berekening staan: komma(energie(12, 10 / 60)) rekent eerst de energie van 10 minuten pompen uit en maakt er dan een tekst van. De docstring is op te vragen met energie.__doc__, of netter met help(energie) in de shell.
return is geen print
Het verschil tussen print en return is de klassieke valkuil bij functies. print toont iets op het scherm; return geeft een waarde terug aan de code die de functie aanriep. Een functie zonder return geeft de speciale waarde None ('niets') terug.
def gemiddelde_print(lijst):
print(sum(lijst) / len(lijst))
def gemiddelde(lijst):
return sum(lijst) / len(lijst)
a = gemiddelde_print([20, 22, 24])
b = gemiddelde([20, 22, 24])
print("a:", a, "- b:", b)22.0 a: None - b: 22.0
De eerste functie toont 22.0, maar a is None: met a kan je niet verder rekenen. Rekenfuncties geven dus terug; alleen het hoofdprogramma toont.
Standaardwaarden. Een parameter mag een standaardwaarde krijgen, zoals decimalen=1. Laat je dat argument weg, dan geldt de standaardwaarde. Argumenten mag je ook met hun naam meegeven, in elke volgorde:
def komma(x, decimalen=1):
return f"{x:.{decimalen}f}".replace(".", ",")
print(komma(3269.5))
print(komma(3269.5, 3))
print(komma(decimalen=0, x=3269.5))3269,5 3269,500 3270
Lokale variabelen. Een variabele die je in een functie maakt, bestaat alleen tijdens die aanroep. Zo kunnen twee functies elk hun eigen totaal hebben zonder elkaar te storen. Wat een functie nodig heeft, geef je mee als argument; wat ze oplevert, geeft ze terug.
Dat je een getal op het scherm ziet, betekent niet dat de functie het teruggeeft. Probeer altijd x = mijn_functie(...) en print(x). Staat er None, dan ontbreekt return.
Een functie voor de vochtsensor
De capacitieve vochtsensor van de meetkas geeft een ruwe ADC-waarde. Bij de ijking (F25) gaf ze 600 in droge potgrond en 300 in natte, en daartussen is het verband lineair: %. Schrijf een functie die een ruwe waarde omzet in een vochtpercentage, ook voor waarden buiten de ijking.
- ijkpunten: ruw 600 → 0 %, ruw 300 → 100 %
- verband: vocht = (600 − ruw) / 3
- een functie vocht_procent(ruw) met docstring
- een test met gekozen waarden
- 1Kop en docstring. Eén parameter (de ruwe waarde), één returnwaarde (het vocht in %). De docstring vermeldt de ijking: wie de sensor later opnieuw ijkt, weet waar de getallen vandaan komen.
- 2Buiten de ijking. Een ruwe waarde van 640 (grond droger dan bij de ijking, of een los draadje) geeft −13 %, en 250 geeft 117 %. Die bestaan niet. Begrenzen doe je met
max(0.0, ...)(niet onder 0) enmin(100.0, ...)(niet boven 100). - 3Testen. Kies waarden waarvan je de uitkomst kent: de twee ijkpunten, de drempel van 30 % (ruw 510), een waarde in het midden, en twee buiten de ijking.
# vochtsensor.py - van ruwe ADC-waarde naar bodemvocht in procent def vocht_procent(ruw): """Bodemvocht (%) uit de ruwe ADC-waarde van de capacitieve sensor. IJking (F25): 600 in droge potgrond, 300 in natte. Begrensd tot 0-100 %. """ vocht = (600 - ruw) / 3 return min(100.0, max(0.0, vocht)) for ruw in (600, 510, 405, 300, 250, 640): print(ruw, "->", round(vocht_procent(ruw), 1), "%")600 -> 0.0 % 510 -> 30.0 % 405 -> 65.0 % 300 -> 100.0 % 250 -> 100.0 % 640 -> 0.0 %
Lijsten: veel waarden onder één naam
Een lijst zet je tussen vierkante haken, met komma's tussen de elementen. Elk element heeft een index: zijn plaats, vanaf 0. Met een negatieve index tel je van achteren: [-1] is het laatste element. Hier de hoogste temperatuur van elke dag van de meetweek:
>>> maxima = [28.1, 25.1, 21.1, 22.8, 27.4, 28.6, 25.1] >>> maxima[0] 28.1 >>> maxima[5] 28.6 >>> maxima[-1] 25.1 >>> len(maxima) 7 >>> 28.6 in maxima True >>> maxima.index(28.6) 5
Een lijst kan groeien en veranderen. Je begint vaak met een lege lijst en voegt met append telkens een meting toe; een element vervang je via zijn index:
>>> metingen = [] >>> metingen.append(19.4) >>> metingen.append(21.0) >>> metingen [19.4, 21.0] >>> metingen[0] = 19.6 >>> metingen [19.6, 21.0] >>> len(metingen) 2
Een lijst mag waarden van elk type bevatten, ook teksten: dagen = ["ma", "di", ...]. Twee lijsten met evenveel elementen (dagen en maxima) horen vaak samen: het element met index 5 in de ene lijst hoort bij index 5 in de andere.
Een lijst met 7 elementen heeft de indexen 0 tot en met 6. maxima[7] bestaat niet en geeft een IndexError. Dit is dezelfde afspraak als bij range(7).
Slicing: een stuk uit een lijst of een tekst
Met lijst[a:b] neem je een stuk (een slice): van index a tot, maar niet met, index b. Laat je a weg, dan begin je vooraan; laat je b weg, dan loop je tot het einde. Een derde getal is de stap, zoals bij range(). Het resultaat is een nieuwe lijst; de oude blijft ongewijzigd.
>>> maxima = [28.1, 25.1, 21.1, 22.8, 27.4, 28.6, 25.1] >>> maxima[1:4] [25.1, 21.1, 22.8] >>> maxima[:3] [28.1, 25.1, 21.1] >>> maxima[5:] [28.6, 25.1] >>> maxima[-2:] [28.6, 25.1] >>> maxima[::2] [28.1, 21.1, 27.4, 25.1]
Een tekst (str) is ook een reeks, van tekens. Daarom werkt slicing ook op tekst, en dat is handig bij datalogbestanden, waar de datum en het uur samen in één tekst staan:
>>> tijdstip = "2026-04-20 06:00" >>> tijdstip[:10] '2026-04-20' >>> tijdstip[11:13] '06' >>> int(tijdstip[11:13]) 6 >>> len(tijdstip) 16
Met tijdstip[:10] groepeer je straks de metingen per dag, met int(tijdstip[11:13]) per uur.
Rekenen met lijsten: len, sum, min, max en sorted
Voor lijsten met getallen heeft Python ingebouwde functies die de statistiek van hoofdstuk 1 in één regel doen. Het gemiddelde is sum(l) / len(l). sorted() geeft een nieuwe, gesorteerde lijst (met reverse=True van groot naar klein); l.index(x) geeft de plaats van x, en met die index zoek je in een tweede lijst op welke dag het was.
# week.py - rekenen met een lijst: de hoogste temperatuur van elke dagdagen = ["ma", "di", "wo", "do", "vr", "za", "zo"]maxima = [28.1, 25.1, 21.1, 22.8, 27.4, 28.6, 25.1] # graden Celsius print("aantal dagen:", len(maxima))print("gemiddeld maximum:", round(sum(maxima) / len(maxima), 1))print("laagste:", min(maxima), "- hoogste:", max(maxima))i = maxima.index(max(maxima))print("warmste dag van de week:", dagen[i])print("gesorteerd:", sorted(maxima))print("drie warmste:", sorted(maxima, reverse=True)[:3])Uitvoer:
aantal dagen: 7 gemiddeld maximum: 25.5 laagste: 21.1 - hoogste: 28.6 warmste dag van de week: za gesorteerd: [21.1, 22.8, 25.1, 25.1, 27.4, 28.1, 28.6] drie warmste: [28.6, 28.1, 27.4]
| schrijfwijze | betekenis | voorbeeld met maxima | uitkomst |
|---|---|---|---|
l[i] | element met index i (vanaf 0) | maxima[2] | 21.1 |
l[-1] | laatste element | maxima[-1] | 25.1 |
l[a:b] | stuk van index a tot (niet met) b | maxima[1:4] | [25.1, 21.1, 22.8] |
len(l) | aantal elementen | len(maxima) | 7 |
sum(l), min(l), max(l) | som, kleinste, grootste | max(maxima) | 28.6 |
sorted(l) | nieuwe, gesorteerde lijst | sorted(maxima)[:3] | [21.1, 22.8, 25.1] |
l.index(x) | index van de eerste x | maxima.index(25.1) | 1 |
l.count(x) | hoe vaak x voorkomt | maxima.count(25.1) | 2 |
x in l | zit x in de lijst? | 30.0 in maxima | False |
[f(x) for x in l if ...] | nieuwe lijst uit een oude | [t for t in maxima if t > 26] | [28.1, 27.4, 28.6] |
l.append(x) | x achteraan toevoegen | verandert de lijst zelf | |
l.copy() | een echte kopie | zonder copy() krijg je een tweede naam voor dezelfde lijst | |
sorted(maxima) maakt een nieuwe lijst en laat maxima ongewijzigd. maxima.sort() sorteert de lijst zelf en geeft None terug. Schrijf dus nooit maxima = maxima.sort(): dan is je lijst weg.
Lussen over lijsten: ophopen, tellen, filteren
Een for-lus loopt niet alleen over range(), maar over elke lijst: de lusvariabele krijgt elke ronde het volgende element. Vier patronen komen steeds terug. Ophopen: een totaal vóór de lus, in de lus erbij tellen. Tellen of filteren: in de lus een if. Twee lijsten tegelijk: met zip(), en met enumerate() krijg je er een volgnummer bij. Een nieuwe lijst maken uit een oude: met append in een lus, of korter met een lijstomschrijving (list comprehension) tussen vierkante haken.
# patronen.py - vier manieren om over een lijst te lopen
dagen = ["ma", "di", "wo", "do", "vr", "za", "zo"]
maxima = [28.1, 25.1, 21.1, 22.8, 27.4, 28.6, 25.1]
totaal = 0 # 1. ophopen
for t in maxima:
totaal = totaal + t
print("som:", round(totaal, 1))
aantal = 0 # 2. tellen met een voorwaarde
for t in maxima:
if t > 26:
aantal = aantal + 1
print("dagen boven 26 graden:", aantal)
for dag, t in zip(dagen, maxima): # 3. twee lijsten tegelijk
if t < 23:
print("koele dag:", dag, t)
for nummer, dag in enumerate(dagen[:3], start=1):
print(nummer, dag)
kelvin = [round(t + 273.15, 2) for t in maxima] # 4. een nieuwe lijst
print(kelvin)som: 178.2 dagen boven 26 graden: 3 koele dag: wo 21.1 koele dag: do 22.8 1 ma 2 di 3 wo [301.25, 298.25, 294.25, 295.95, 300.55, 301.75, 298.25]
De lijstomschrijving [round(t + 273.15, 2) for t in maxima] leest als 'voor elke t in maxima: t in kelvin'. Met een if erachter filter je: [t for t in maxima if t > 26] geeft alleen de warme dagen.
Een gewone lus met append is altijd goed. Een lijstomschrijving is korter, maar schrijf ze alleen als ze op één regel leesbaar blijft.
Gemiddelde en maximum zelf programmeren
sum(), len() en max() doen het werk voor je, maar hoe werken ze? Schrijf zelf een functie voor het gemiddelde en een voor de grootste waarde, test ze op de zonnestroom per dag van de meetweek, en vergelijk met de ingebouwde functies.
- zonnestroom per dag (Wh), maandag tot zondag: 7465, 5105, 1547, 3077, 6949, 7717, 4676
- functies gemiddelde(waarden) en grootste(waarden)
- een trace van grootste()
- 1Gemiddelde. Het patroon ophopen:
totaal = 0, in de lus elke waarde erbij, na de lus delen door het aantal. Een lege lijst zou een deling door nul geven; de docstring zegt dat ze niet leeg mag zijn. - 2Grootste. Hetzelfde idee als bij het sorteren van kaarten in F22, waar je telkens de kleinste zocht: neem de eerste waarde als voorlopig beste en vergelijk elke volgende waarde ermee; is ze groter, dan wordt zij de nieuwe beste.
waarden[1:]slaat de eerste over, want die is al de beste. - 3Het programma:
# statistiek.py - gemiddelde en maximum zelf uitrekenen def gemiddelde(waarden): """Rekenkundig gemiddelde van een lijst getallen (de lijst mag niet leeg zijn).""" totaal = 0 for w in waarden: totaal = totaal + w return totaal / len(waarden) def grootste(waarden): """Grootste waarde van een lijst, zonder max().""" beste = waarden[0] for w in waarden[1:]: if w > beste: beste = w return beste zon = [7465, 5105, 1547, 3077, 6949, 7717, 4676] # Wh per dag, maandag tot zondag print("gemiddeld:", round(gemiddelde(zon)), "Wh - met sum/len:", round(sum(zon) / len(zon))) print("grootste:", grootste(zon), "Wh - met max():", max(zon))gemiddeld: 5219 Wh - met sum/len: 5219 grootste: 7717 Wh - met max(): 7717
- 4Trace van grootste(). Beste begint op 7465.
w w > beste? beste daarna 5105 nee 7465 1547 nee 7465 3077 nee 7465 6949 nee 7465 7717 ja 7717 4676 nee 7717
beste = 0 als begin kiest in plaats van de eerste waarde, krijgt bij een lijst met alleen negatieve temperaturen 0 als maximum: een klassieke fout.Woordenboeken: opzoeken met een sleutel
In een lijst zoek je een waarde op met een getal (de index). In een woordenboek (dictionary, type dict) zoek je op met een sleutel, meestal een tekst. Je schrijft het tussen accolades, met paren sleutel: waarde. Een voorbeeld is de pintabel van de Arduino Mega van de klimaatmodule:
>>> pinnen = {"A0": "NTC reservoir", "A1": "LDR", "A2": "pH-module", "A3": "batterijdeler"}
>>> pinnen["A2"]
'pH-module'
>>> pinnen["D9"] = "pomp (MOSFET)"
>>> len(pinnen)
5
>>> "A5" in pinnen
False
>>> pinnen.get("A5", "vrij")
'vrij'Over alle paren loop je met items():
for pin, onderdeel in pinnen.items():
print(pin, "->", onderdeel)A0 -> NTC reservoir A1 -> LDR A2 -> pH-module A3 -> batterijdeler D9 -> pomp (MOSFET)
| schrijfwijze | betekenis |
|---|---|
d = {"A0": "NTC", "A1": "LDR"} | woordenboek met sleutels en waarden |
d["A0"] | waarde opzoeken (KeyError als de sleutel ontbreekt) |
d["D9"] = "pomp" | toevoegen of vervangen |
d.get("A5", "vrij") | opzoeken met een standaardwaarde |
"A5" in d | bestaat de sleutel? |
for k, w in d.items(): | over alle paren lopen |
d.keys(), d.values(), len(d) | sleutels, waarden, aantal paren |
Een woordenboek is ook de handigste manier om metingen per groep te verzamelen: de sleutel is de datum (of het dagdeel), de waarde een lijst met de metingen van die groep. Dat doe je verderop met de meetweek.
Een lijst als de volgorde telt en de waarden van dezelfde soort zijn (de temperatuur elk uur). Een woordenboek als je iets opzoekt met een naam (welke sensor op A2 zit, hoeveel watt de pomp verbruikt).
Habitat: het energiebudget met een woordenboek en functies
De rekenhulp van hoofdstuk 27 rekende één maand tegelijk; voor een andere maand moest je twee regels aanpassen. Met een woordenboek voor de verbruikers, een lijst met de twaalf PVGIS-waarden en drie functies rekent hetzelfde programma het hele jaar door. In de for-lus over items() pakt naam, (vermogen, uren) elk paar meteen uit.
# budget_maanden.py - de rekenhulp van hoofdstuk 27 met een woordenboek, lijsten en functiesVERBRUIKERS = { # naam: (vermogen in W, uren per dag) "groeilampen": (190, 16), "pomp": (12, 4), "sensoren": (3.0, 24), "ventilatie dag": (5, 16), "ventilatie nacht": (2, 8), "CO2-klep": (6, 0.25), "BMS": (0.5, 24),}MAANDEN = ['jan', 'feb', 'mrt', 'apr', 'mei', 'jun', 'jul', 'aug', 'sep', 'okt', 'nov', 'dec']WH_PER_WP = [1.41, 2.11, 2.99, 3.69, 3.58, 3.54, 3.45, 3.31, 3.29, 2.5, 1.66, 1.25]PIEK = 4 * 350 # Wp def verbruik_per_dag(lichturen=16): """Verbruik van de module in Wh per dag, als de groeilampen 'lichturen' uur branden.""" totaal = 0 for naam, (vermogen, uren) in VERBRUIKERS.items(): if naam == "groeilampen": uren = lichturen totaal = totaal + vermogen * uren return totaal def zon_per_dag(maand): """Zonnestroom in Wh per dag in maand 1 tot 12 (PVGIS, Brussel, 60 graden zuid).""" return PIEK * WH_PER_WP[maand - 1] def max_lichturen(maand): """Hoeveel lichturen de zonnestroom alleen kan betalen (hoogstens 16).""" for uren in range(16, -1, -1): if verbruik_per_dag(uren) <= zon_per_dag(maand): return uren return 0 print("maand zon saldo lichturen")for m in range(1, 13): saldo = zon_per_dag(m) - verbruik_per_dag() print(f"{MAANDEN[m - 1]:5} {zon_per_dag(m):5.0f} {saldo:+6.0f} {max_lichturen(m):6d}")Uitvoer:
maand zon saldo lichturen jan 1974 -1296 9 feb 2954 -316 14 mrt 4186 +916 16 apr 5166 +1896 16 mei 5012 +1742 16 jun 4956 +1686 16 jul 4830 +1560 16 aug 4634 +1364 16 sep 4606 +1336 16 okt 3500 +230 16 nov 2324 -946 11 dec 1750 -1520 8
De kolom lichturen is precies wat de rekenhulp van hoofdstuk 27 één maand per keer gaf. Het verschil: een verbruiker toevoegen is nu één regel in het woordenboek, en elke functie is apart te testen. max_lichturen gebruikt return midden in een lus: zodra de voorwaarde klopt, stopt de functie.
CSV: een tabel als tekst
Een CSV-bestand (comma-separated values) is een tabel als gewone tekst: één rij per regel, de kolommen gescheiden door komma's. De eerste regel is meestal de kop met de namen van de kolommen. Elk rekenblad kan CSV openen en bewaren, elke datalogger kan het schrijven, en je leest het met een teksteditor. Daarom is het het meest gebruikte formaat voor meetdata.
Het bestand van de klimaatmodule heeft vijf kolommen: het tijdstip (datum en uur, zoals '2026-04-20 06:00'), de temperatuur in °C en de vochtigheid in % (gemiddelden over de drie uur die op dat tijdstip beginnen), en het verbruik en de zonnestroom in Wh in diezelfde drie uur. De eenheid staat in de naam van de kolom: temperatuur_C, verbruik_Wh. Een lege cel betekent: geen meting.
In het Nederlands is de komma het decimaalteken. Een rekenblad met Belgische of Nederlandse instellingen bewaart 'CSV' daarom vaak met een puntkomma tussen de kolommen en een komma in de getallen: 2026-04-20 06:00;19,9;78;571;126, en soms schrijft het de datum anders (20/04/2026 6:00). Kijk zo'n bestand eerst na in een teksteditor. Lees het met csv.DictReader(bestand, delimiter=";") en zet elk getal om met float(tekst.replace(",", ".")). Bewaart het rekenblad als 'CSV UTF-8', dan staat er vaak een onzichtbaar teken vooraan het bestand; open het dan met encoding="utf-8-sig", anders heet je eerste kolom niet 'tijdstip'.
Heet je eigen bestand csv.py, dan laadt import csv jouw bestand in plaats van de module, en krijg je rare foutmeldingen.
Het bestand: een week in de klimaatmodule
Dit is het volledige bestand: van maandag 20 tot zondag 26 april 2026, om de drie uur een regel, 56 rijen onder de kop. Met de knop Download bewaar je het als klimaatmodule_week.csv, in dezelfde map als je programma's. Kijk er eerst zelf naar: welke dagen waren zonnig? En waar ontbreekt een meting?
tijdstip,temperatuur_C,vocht_pct,verbruik_Wh,zon_Wh2026-04-20 00:00,18.6,84,22,02026-04-20 03:00,18.5,83,22,02026-04-20 06:00,19.9,78,571,1262026-04-20 09:00,23.6,71,172,17582026-04-20 12:00,28.0,63,90,27992026-04-20 15:00,28.1,63,88,22912026-04-20 18:00,23.7,69,482,4912026-04-20 21:00,20.1,79,216,02026-04-21 00:00,18.5,84,22,02026-04-21 03:00,17.8,84,22,02026-04-21 06:00,19.4,79,578,952026-04-21 09:00,22.3,77,283,13052026-04-21 12:00,25.1,66,169,17762026-04-21 15:00,25.1,66,225,15402026-04-21 18:00,22.1,75,506,3892026-04-21 21:00,19.7,81,216,02026-04-22 00:00,18.2,83,22,02026-04-22 03:00,17.7,82,22,02026-04-22 06:00,19.2,83,595,252026-04-22 09:00,19.7,78,525,3142026-04-22 12:00,,78,454,6112026-04-22 15:00,21.1,76,483,4842026-04-22 18:00,20.3,80,574,1132026-04-22 21:00,19.1,83,216,02026-04-23 00:00,18.5,83,22,02026-04-23 03:00,17.8,83,22,02026-04-23 06:00,19.6,81,587,582026-04-23 09:00,20.9,78,431,6982026-04-23 12:00,22.8,73,317,11722026-04-23 15:00,22.7,76,371,9422026-04-23 18:00,21.1,77,551,2072026-04-23 21:00,19.1,84,216,02026-04-24 00:00,18.9,80,22,02026-04-24 03:00,18.4,83,22,02026-04-24 06:00,19.9,81,571,1252026-04-24 09:00,23.4,71,189,16902026-04-24 12:00,27.4,65,90,26642026-04-24 15:00,27.1,64,113,20002026-04-24 18:00,23.4,73,487,4702026-04-24 21:00,19.5,83,216,02026-04-25 00:00,19.1,83,22,02026-04-25 03:00,18.5,84,22,02026-04-25 06:00,20.4,80,569,1322026-04-25 09:00,24.0,71,138,18962026-04-25 12:00,28.6,61,90,29982026-04-25 15:00,28.2,63,88,21862026-04-25 18:00,24.1,72,478,5052026-04-25 21:00,20.4,81,216,02026-04-26 00:00,18.7,82,22,02026-04-26 03:00,18.2,85,22,02026-04-26 06:00,19.6,81,582,812026-04-26 09:00,22.6,72,289,12802026-04-26 12:00,25.1,68,156,18292026-04-26 15:00,24.6,71,310,11942026-04-26 18:00,22.1,74,530,2922026-04-26 21:00,19.2,84,216,0Wat je al ziet zonder te rekenen: 's nachts is het verbruik 22 Wh per blok (sensoren, pomp, ventilator, batterijbeheer) en de zonnestroom 0. Overdag bepalen de groeilampen het verbruik, en die dimmen als er daglicht is: op een zonnige middag zakt het verbruik tot 90 Wh per blok. Woensdag 22 april om 12 uur is de temperatuurcel leeg: de sensor gaf die keer geen geldige waarde. Een programma moet dat opvangen, en mag die cel zeker niet als 0 °C meetellen.
CSV inlezen met de csv-module
Met with open(...) as bestand: open je het bestand; na het ingesprongen blok sluit Python het vanzelf. csv.DictReader leest de kop en geeft daarna elke rij als een woordenboek, met de kolomnamen als sleutels: rij["zon_Wh"]. Alle waarden zijn tekst, zoals bij input(): zet ze om met int() of float(). continue springt meteen naar de volgende ronde van de lus, zodat een lege temperatuur niet omgezet wordt.
# inlezen.py - de metingen van een week inlezen met de csv-moduleimport csv tijden = []temperaturen = []verbruik = []zon = []ontbrekend = 0 with open("klimaatmodule_week.csv", newline="", encoding="utf-8") as bestand: for rij in csv.DictReader(bestand): verbruik.append(int(rij["verbruik_Wh"])) zon.append(int(rij["zon_Wh"])) if rij["temperatuur_C"] == "": # de sensor gaf geen waarde ontbrekend = ontbrekend + 1 continue tijden.append(rij["tijdstip"]) temperaturen.append(float(rij["temperatuur_C"])) print("rijen:", len(verbruik), "- met temperatuur:", len(temperaturen), "- ontbrekend:", ontbrekend)print("eerste meting:", tijden[0], temperaturen[0])print("gemiddelde temperatuur:", round(sum(temperaturen) / len(temperaturen), 1))print("laagste:", min(temperaturen), "- hoogste:", max(temperaturen))print("het warmst op", tijden[temperaturen.index(max(temperaturen))])print("in de hele week: verbruik", sum(verbruik), "Wh, zonnestroom", sum(zon), "Wh")Uitvoer (met het bestand in dezelfde map):
rijen: 56 - met temperatuur: 55 - ontbrekend: 1 eerste meting: 2026-04-20 00:00 18.6 gemiddelde temperatuur: 21.4 laagste: 17.7 - hoogste: 28.6 het warmst op 2026-04-25 12:00 in de hele week: verbruik 14552 Wh, zonnestroom 36536 Wh
De lijsten tijden en temperaturen blijven even lang, omdat ze samen gevuld worden, ná de test op een lege cel. Zo hoort het tijdstip met index i altijd bij de temperatuur met index i, en vind je met temperaturen.index(max(temperaturen)) het moment van het maximum.
Met csv.reader(bestand) krijg je elke rij als lijst van teksten, ['2026-04-20 00:00', '18.6', '84', '22', '0'], en is de kop gewoon de eerste rij. DictReader is leesbaarder (rij["zon_Wh"] in plaats van rij[4]) en blijft werken als er later een kolom bijkomt.
Wanneer was het te warm, en wat deed de zon met het verbruik?
Sla verdraagt warmte slecht; boven ongeveer 26 °C wil de beheerder van de klimaatmodule dat opvolgen. Zoek in de meetweek alle blokken boven 26 °C. Onderzoek ook of de module minder verbruikt als de zon schijnt, zoals je zou verwachten van lampen die dimmen.
- klimaatmodule_week.csv
- lampen aan van 6 tot 22 uur: de blokken van 6, 9, 12, 15 en 18 uur hebben drie volle lichturen
- de warme blokken en hun aantal uren
- het gemiddelde verbruik per blok bij veel en bij weinig zon
- 1Filteren. Een lege lijst
warm, en in de lus een if met twee voorwaarden: de cel is niet leeg en de temperatuur is hoger dan 26. De volgorde telt: doorandwordt float() niet meer uitgevoerd als de cel leeg is. - 2Het uur uit de tekst.
int(rij["tijdstip"][11:13])geeft het uur. Alleen de blokken van 6 tot en met 18 uur tellen mee voor de vergelijking: 's nachts is de zon 0 én zijn de lampen uit, dat zou de vergelijking scheeftrekken. - 3Twee groepen. Veel zon: meer dan 1500 Wh in drie uur (gemiddeld 500 W op 1400 Wp). Weinig zon: minder dan 500 Wh. De blokken daartussen laat je weg, zodat de groepen duidelijk verschillen.
# te_warm.py - wanneer was het warmer dan 26 graden, en wat deed de zon met het verbruik? import csv warm = [] veel_zon = [] weinig_zon = [] with open("klimaatmodule_week.csv", newline="", encoding="utf-8") as bestand: for rij in csv.DictReader(bestand): uur = int(rij["tijdstip"][11:13]) if rij["temperatuur_C"] != "" and float(rij["temperatuur_C"]) > 26: warm.append(rij["tijdstip"]) if 6 <= uur <= 18: # blokken waarin de lampen drie uur mogen branden if int(rij["zon_Wh"]) > 1500: veel_zon.append(int(rij["verbruik_Wh"])) elif int(rij["zon_Wh"]) < 500: weinig_zon.append(int(rij["verbruik_Wh"])) print("boven 26 graden:", len(warm), "blokken, of", 3 * len(warm), "uur:") for t in warm: print(" ", t) print(f"verbruik per blok bij veel zon: {sum(veel_zon) / len(veel_zon):.0f} Wh ({len(veel_zon)} blokken)") print(f"verbruik per blok bij weinig zon: {sum(weinig_zon) / len(weinig_zon):.0f} Wh ({len(weinig_zon)} blokken)")boven 26 graden: 6 blokken, of 18 uur: 2026-04-20 12:00 2026-04-20 15:00 2026-04-24 12:00 2026-04-24 15:00 2026-04-25 12:00 2026-04-25 15:00 verbruik per blok bij veel zon: 134 Wh (12 blokken) verbruik per blok bij weinig zon: 546 Wh (15 blokken)
De week per dag samenvatten
Een woordenboek verzamelt de rijen per dag: de sleutel is de datum (rij["tijdstip"][:10]), de waarde een lijst met de rijen van die dag. Bestaat de sleutel nog niet, dan maak je eerst een lege lijst. Een functie vat één dag samen en geeft vijf waarden tegelijk terug; bij de aanroep pak je ze uit in vijf variabelen.
# per_dag.py - de week per dag samenvattenimport csv per_dag = {} # datum -> lijst met de rijen van die dagwith open("klimaatmodule_week.csv", newline="", encoding="utf-8") as bestand: for rij in csv.DictReader(bestand): datum = rij["tijdstip"][:10] # "2026-04-20 06:00" -> "2026-04-20" if datum not in per_dag: per_dag[datum] = [] per_dag[datum].append(rij) def samenvatting(rijen): """Gemiddelde, laagste en hoogste temperatuur, verbruik en zonnestroom van een dag.""" temp = [float(r["temperatuur_C"]) for r in rijen if r["temperatuur_C"] != ""] verbruik = sum([int(r["verbruik_Wh"]) for r in rijen]) zon = sum([int(r["zon_Wh"]) for r in rijen]) return sum(temp) / len(temp), min(temp), max(temp), verbruik, zon print("datum T gem T min T max verbruik zon saldo")for datum, rijen in per_dag.items(): gem, laag, hoog, verbruik, zon = samenvatting(rijen) print(f"{datum} {gem:5.1f} {laag:6.1f} {hoog:6.1f} {verbruik:9d} {zon:6d} {zon - verbruik:+7d}")Uitvoer:
datum T gem T min T max verbruik zon saldo 2026-04-20 22.6 18.5 28.1 1663 7465 +5802 2026-04-21 21.2 17.8 25.1 2021 5105 +3084 2026-04-22 19.3 17.7 21.1 2891 1547 -1344 2026-04-23 20.3 17.8 22.8 2517 3077 +560 2026-04-24 22.2 18.4 27.4 1710 6949 +5239 2026-04-25 22.9 18.5 28.6 1623 7717 +6094 2026-04-26 21.3 18.2 25.1 2127 4676 +2549
Wat de tabel vertelt: op zonnige dagen (maandag, vrijdag, zaterdag) is het warmst, verbruikt de module het minst (de lampen dimmen) en blijft er het meest zonnestroom over. Alleen op de regendag (woensdag) is het saldo negatief: dan moet de batterij bijspringen. De temperatuur van woensdag is een gemiddelde over zeven blokken, omdat er één ontbreekt; ze telt dus iets minder zwaar mee dan de andere dagen.
Van meting tot bestand: het klaslokaal een lesuur lang
Hoe verandert de temperatuur in het klaslokaal tijdens een lesuur, en wat doet een open raam?
- een thermometer met een resolutie van 0,1 °C (of een temperatuursensor op een microcontroller)
- een horloge of de klok van de computer
- een teksteditor (Kladblok, of de editor van Thonny)
- Python met het programma klaslokaal.py
- 1Hang de thermometer op 1,5 m hoogte, uit de zon en weg van de verwarming.
- 2Noteer om de 5 minuten de temperatuur, een lesuur lang. Zet na 30 minuten een raam wijd open en noteer het tijdstip.
- 3Typ de metingen in een teksteditor als CSV: eerst de kop
tijd,temperatuur_C, dan één regel per meting, met een decimale punt. Bewaar alsklaslokaal.csvin UTF-8. - 4Draai het programma: het leest de kolom met een eigen functie en toont gemiddelde, minimum, maximum en de verandering per 5 minuten.
- 5Maak met matplotlib een grafiek (pas grafiek_week.py aan) en zet een verticale lijn op het moment dat het raam openging (
plt.axvline(30)).
Een voorbeeld van één klas (klaslokaal.csv):
tijd,temperatuur_C 08:30,19.2 08:35,19.5 08:40,19.8 08:45,20.2 08:50,20.5 08:55,20.9 09:00,21.1 09:05,19.8 09:10,19.4 09:15,19.6
# klaslokaal.py - de temperatuur in het klaslokaal, een lesuur lang
import csv
def lees_kolom(naam, kolom):
"""Alle niet-lege waarden van een kolom uit een CSV-bestand, als kommagetallen."""
waarden = []
with open(naam, newline="", encoding="utf-8") as bestand:
for rij in csv.DictReader(bestand):
if rij[kolom] != "":
waarden.append(float(rij[kolom]))
return waarden
temp = lees_kolom("klaslokaal.csv", "temperatuur_C")
print("metingen:", len(temp))
print(f"gemiddeld {sum(temp) / len(temp):.1f} graden, laagst {min(temp)}, hoogst {max(temp)}")
verschil = [round(temp[i + 1] - temp[i], 1) for i in range(len(temp) - 1)]
print("verandering per 5 minuten:", verschil)
print("grootste daling:", min(verschil))Uitvoer:
metingen: 10 gemiddeld 20.0 graden, laagst 19.2, hoogst 21.1 verandering per 5 minuten: [0.3, 0.3, 0.4, 0.3, 0.4, 0.2, -1.3, -0.4, 0.2] grootste daling: -1.3
Een klas van twintig leerlingen verwarmt het lokaal: elke persoon geeft ongeveer 100 W warmte af (hoofdstuk 14 rekende met ±116 W voor een bewoner). Dat is 2 kW, zoveel als een elektrische kachel. Met het raam open komt koude lucht binnen en zakt de temperatuur in vijf minuten meer dan een graad. Daarna stijgt ze weer licht: de muren en meubels hebben warmte opgeslagen en geven die af (hoofdstuk 18). De functie lees_kolom is bruikbaar voor elk CSV-bestand: voor de klimaatmodule roep je ze aan met een andere bestandsnaam en kolomnaam. Dat is de winst van een goede functie.

Grafieken met matplotlib
matplotlib is de bekendste Python-bibliotheek voor grafieken. Je installeert ze één keer (in een terminal: pip install matplotlib, in Thonny via Tools, Manage packages). De module pyplot importeer je met de korte naam plt. Het programma leest de temperaturen en de tijd in dagen, en tekent ze als lijn met punten. plt.savefig() bewaart de grafiek als afbeelding voor je verslag; plt.show() opent ze in een venster.
# grafiek_week.py - de temperatuur van een week in een grafiekimport csvimport matplotlib.pyplot as plt dagen = [] # tijd in dagen sinds maandag 0 uurtemperaturen = []with open("klimaatmodule_week.csv", newline="", encoding="utf-8") as bestand: for i, rij in enumerate(csv.DictReader(bestand)): if rij["temperatuur_C"] != "": dagen.append(i * 3 / 24) # rij i begint i * 3 uur na maandag 0 uur temperaturen.append(float(rij["temperatuur_C"])) plt.plot(dagen, temperaturen, marker="o", label="temperatuur (gemiddelde per 3 uur)")plt.axhline(26, linestyle="--", color="gray")plt.xlabel("tijd (dagen sinds maandag 20 april, 0 uur)")plt.ylabel("temperatuur (°C)")plt.title("Klimaatmodule, week van 20 april 2026")plt.grid(True)plt.legend()plt.savefig("temperatuur_week.png", dpi=150)plt.show()De code geeft dezelfde grafiek als hiernaast: dezelfde punten, dezelfde assen, de hulplijn op 26 °C (plt.axhline). matplotlib gebruikt haar eigen kleuren en schrijft getallen met een decimale punt. De grafieken in dit boek zijn met dezelfde gegevens getekend in de huisstijl, zodat ze ook op papier en in het donkere thema leesbaar zijn. Het ontbrekende punt van woensdagmiddag is gewoon overgeslagen: de lijn loopt van 9 naar 15 uur.
Een staafdiagram maak je met plt.bar. Twee reeksen naast elkaar schuif je elk 0,2 opzij, met een breedte van 0,4; plt.xticks zet de namen van de dagen onder de staven. De getallen komen uit per_dag.py (in kWh):
# energie_week.py - verbruik en zonnestroom per dag als staafdiagram
import matplotlib.pyplot as plt
dagen = ["ma", "di", "wo", "do", "vr", "za", "zo"]
verbruik = [1.66, 2.02, 2.89, 2.52, 1.71, 1.62, 2.13] # kWh per dag, uit per_dag.py
zon = [7.46, 5.11, 1.55, 3.08, 6.95, 7.72, 4.68]
x = range(len(dagen))
plt.bar([i - 0.2 for i in x], verbruik, width=0.4, label="verbruik")
plt.bar([i + 0.2 for i in x], zon, width=0.4, label="zonnestroom")
plt.xticks(x, dagen)
plt.ylabel("energie per dag (kWh)")
plt.legend()
plt.show()Die code tekent het staafdiagram van het blad 'De week per dag samenvatten'.
Elke as krijgt een grootheid en een eenheid, elke reeks een label in de legende. Een titel is handig op het scherm; in een verslag komt de uitleg in het onderschrift.
Een goede grafiek ontleed
Dezelfde grafiek, met bij elk onderdeel de regel matplotlib die het tekent. Een grafiek zonder één van deze onderdelen is moeilijker te lezen, of zegt zelfs iets anders dan de data (hoofdstuk 39).
- 1Datapunten en lijn
plt.plot(dagen, temperaturen, marker="o"): punten op de gemeten waarden, verbonden door een lijn omdat de tijd doorloopt. Het hoogste punt: zaterdag 12 uur, 28,6 °C. - 2Hulplijn
plt.axhline(26, linestyle="--"): een grens die de lezer helpt, hier 26 °C. - 3x-as met grootheid en eenheid
plt.xlabel(...): wat staat er horizontaal, en vanaf wanneer telt de tijd? - 4y-as met grootheid en eenheid
plt.ylabel("temperatuur (°C)"). De as begint hier bij 16 °C, niet bij 0: dat mag, als je het ziet aan de getallen. - 5Legende
label="..."in plt.plot en daarnaplt.legend(): nodig zodra er meer dan één reeks is. - 6Raster
plt.grid(True): lichte lijnen om waarden af te lezen. De stap (1 dag, 2 °C) kies je zo dat de getallen rond zijn.
Foutmeldingen en valkuilen bij lijsten, woordenboeken en functies
Met lijsten, woordenboeken en functies komen er nieuwe foutmeldingen bij. Lees ze zoals in hoofdstuk 27: van onder naar boven. Nieuw is dat een traceback door een functie heen loopt: dan staan er twee plaatsen, de aanroep en de regel in de functie. De echte meldingen van Python 3.13:
IndexError. Drie elementen hebben de indexen 0, 1 en 2. De laatste is temperaturen[-1] of temperaturen[len(temperaturen) - 1].
temperaturen = [19.4, 21.0, 23.5]
print(temperaturen[3])Traceback (most recent call last):
File "fouten.py", line 2, in <module>
print(temperaturen[3])
~~~~~~~~~~~~^^^
IndexError: list index out of rangeKeyError. De sleutel bestaat niet. Test eerst met in, of gebruik pinnen.get("A2", "vrij"). Bij een CSV-bestand is het vaak een tikfout in de kolomnaam.
pinnen = {"A0": "NTC", "A1": "LDR"}
print(pinnen["A2"])Traceback (most recent call last):
File "fouten.py", line 2, in <module>
print(pinnen["A2"])
~~~~~~^^^^^^
KeyError: 'A2'AttributeError. Een lijst kent geen push (dat is JavaScript); in Python is het append.
metingen = [19.4, 21.0]
metingen.push(23.5)Traceback (most recent call last):
File "fouten.py", line 2, in <module>
metingen.push(23.5)
^^^^^^^^^^^^^
AttributeError: 'list' object has no attribute 'push'TypeError. De functie heeft twee parameters en krijgt maar één argument. Geef ze allebei mee, of geef de parameter een standaardwaarde.
def energie(vermogen, uren):
return vermogen * uren
print(energie(190))Traceback (most recent call last):
File "fouten.py", line 5, in <module>
print(energie(190))
~~~~~~~^^^^^
TypeError: energie() missing 1 required positional argument: 'uren'ZeroDivisionError. De traceback heeft nu twee niveaus: regel 5 riep de functie aan, en in de functie (regel 2) liep het mis. Een lege lijst heeft lengte 0. Zeg in de docstring dat de lijst niet leeg mag zijn, of test het: if len(lijst) == 0: return None.
def gemiddelde(lijst):
return sum(lijst) / len(lijst)
print(gemiddelde([]))Traceback (most recent call last):
File "fouten.py", line 5, in <module>
print(gemiddelde([]))
~~~~~~~~~~^^^^
File "fouten.py", line 2, in gemiddelde
return sum(lijst) / len(lijst)
~~~~~~~~~~~^~~~~~~~~~~~
ZeroDivisionError: division by zeroEen naam is een naamkaartje (hoofdstuk 27). Na b = a hangen twee kaartjes aan dezelfde lijst: wie via b iets toevoegt, verandert ook a. Wil je een echte kopie, schrijf dan b = a.copy().
>>> a = [19.4, 21.0] >>> b = a >>> b.append(23.5) >>> a [19.4, 21.0, 23.5] >>> c = a.copy() >>> c.append(99) >>> a [19.4, 21.0, 23.5]
Bij getallen en teksten merk je dit nooit, omdat je die niet kan veranderen: x = x + 1 maakt een nieuwe waarde.
Functies, lijsten, woordenboeken, CSV en matplotlib
De schrijfwijzen uit dit hoofdstuk op één blad.
| schrijfwijze | betekenis |
|---|---|
def naam(a, b=2): | functie met een verplichte parameter a en een parameter b met standaardwaarde 2 |
"""Uitleg.""" | docstring: eerste regel in de functie, zegt wat ze doet |
return waarde | geeft de waarde terug en stopt de functie; zonder return krijg je None |
x = naam(5), naam(5, b=3) | aanroepen, met argumenten op volgorde of met hun naam |
return a, b en x, y = naam(...) | twee waarden teruggeven en uitpakken |
| schrijfwijze | betekenis | voorbeeld met maxima | uitkomst |
|---|---|---|---|
l[i] | element met index i (vanaf 0) | maxima[2] | 21.1 |
l[-1] | laatste element | maxima[-1] | 25.1 |
l[a:b] | stuk van index a tot (niet met) b | maxima[1:4] | [25.1, 21.1, 22.8] |
len(l) | aantal elementen | len(maxima) | 7 |
sum(l), min(l), max(l) | som, kleinste, grootste | max(maxima) | 28.6 |
sorted(l) | nieuwe, gesorteerde lijst | sorted(maxima)[:3] | [21.1, 22.8, 25.1] |
l.index(x) | index van de eerste x | maxima.index(25.1) | 1 |
l.count(x) | hoe vaak x voorkomt | maxima.count(25.1) | 2 |
x in l | zit x in de lijst? | 30.0 in maxima | False |
[f(x) for x in l if ...] | nieuwe lijst uit een oude | [t for t in maxima if t > 26] | [28.1, 27.4, 28.6] |
l.append(x) | x achteraan toevoegen | verandert de lijst zelf | |
l.copy() | een echte kopie | zonder copy() krijg je een tweede naam voor dezelfde lijst | |
| schrijfwijze | betekenis |
|---|---|
d = {"A0": "NTC", "A1": "LDR"} | woordenboek met sleutels en waarden |
d["A0"] | waarde opzoeken (KeyError als de sleutel ontbreekt) |
d["D9"] = "pomp" | toevoegen of vervangen |
d.get("A5", "vrij") | opzoeken met een standaardwaarde |
"A5" in d | bestaat de sleutel? |
for k, w in d.items(): | over alle paren lopen |
d.keys(), d.values(), len(d) | sleutels, waarden, aantal paren |
| schrijfwijze | betekenis |
|---|---|
import csv | de csv-module laden |
with open(naam, newline="", encoding="utf-8") as f: | bestand openen; het sluit vanzelf na het blok |
csv.DictReader(f) | elke rij als woordenboek met de kop als sleutels |
csv.reader(f) | elke rij als lijst van teksten |
delimiter=";", encoding="utf-8-sig" | voor een CSV uit een Nederlandstalig rekenblad |
import matplotlib.pyplot as plt | matplotlib laden (eenmalig installeren: pip install matplotlib) |
plt.plot(x, y, marker="o", label="...") | lijngrafiek met punten |
plt.bar(x, hoogte, width=0.4), plt.scatter(x, y) | staafdiagram, puntenwolk |
plt.xlabel(), plt.ylabel(), plt.title() | asopschriften (grootheid en eenheid) en titel |
plt.legend(), plt.grid(True), plt.axhline(26) | legende, raster, horizontale hulplijn |
plt.savefig("naam.png", dpi=150), plt.show() | bewaren als afbeelding, tonen in een venster |
Waar data in Python vandaan komt en waar ze heen gaat
Met functies, lijsten en bestanden kan je programma omgaan met echte hoeveelheden data. Dat verbindt programmeren met onderzoeken en meten (een meting is pas iets waard als je ze betrouwbaar samenvat) en met data en AI (een model leert uit precies zulke tabellen). Wiskundig oefen je gemiddelden, sommen en verbanden; technisch lees je het energiebudget en de klimaatregeling af uit echte cijfers.
Tabel en grafiek: grootheid, eenheid, schaal. matplotlib volgt dezelfde regels.
Gemiddelde, bereik en uitschieters; in code voor honderden metingen tegelijk.
Een verband in data zoeken; het rekenblad dat je hier door code vervangt.
Het energiebudget en de PVGIS-waarden achter budget_maanden.py.
De ruwe ADC-waarden die vocht_procent() omrekent, en het dimmen van de lampen.
Variabelen, keuzes, lussen en foutmeldingen: de basis onder dit hoofdstuk.
De datalogger die zulke CSV-bestanden schrijft, en ze in Python visualiseren.
De juiste grafiek kiezen, misleidende grafieken, en correlatie tegenover oorzaak.
Standaardafwijking, betrouwbaarheidsintervallen en toetsen op zulke data.
Functies en data samen in klassen, en functies testen met unit tests.
numpy rekent met hele lijsten tegelijk: sneller en korter dan een lus.
In het kort
def naam(parameters):maakt een functie; de docstring zegt wat ze doet,returngeeft een waarde terug. Zonder return krijg je None.- print toont, return geeft terug: rekenfuncties geven terug, het hoofdprogramma toont. Standaardwaarden maken een argument optioneel.
- Een lijst
[...]heeft indexen vanaf 0;[-1]is het laatste element,l[a:b]een stuk zonder index b. append voegt toe. - len, sum, min, max en sorted rekenen op een lijst; het gemiddelde is sum / len. Een maximum zoek je zelf met een voorlopige beste.
- Een lus over een lijst hoopt op, telt, filtert of maakt een nieuwe lijst; zip loopt over twee lijsten tegelijk.
- Een woordenboek
{sleutel: waarde}zoekt op met een naam en verzamelt metingen per groep. - CSV is een tabel als tekst. csv.DictReader geeft elke rij als woordenboek met teksten: omzetten, en lege cellen overslaan.
- matplotlib tekent met plot, bar en scatter; elke as krijgt een grootheid en een eenheid, elke reeks een label.
- b = a kopieert een lijst niet: gebruik a.copy().
Wat je nu kent
- functie
- Een stuk code met een naam dat je kan aanroepen; het krijgt argumenten mee en geeft met return een waarde terug.
- parameter
- De naam in de functiedefinitie die bij een aanroep de waarde van een argument krijgt, zoals vermogen in energie(vermogen, uren).
- returnwaarde
- Wat een functie met return teruggeeft aan wie haar aanriep; zonder return is dat None.
- docstring
- De tekst tussen drie aanhalingstekens op de eerste regel van een functie, die zegt wat ze doet.
- lijst
- Een geordende reeks waarden onder één naam, tussen vierkante haken; het eerste element heeft index 0.
- slicing
- Een stuk uit een lijst of tekst nemen met l[a:b]: van index a tot, maar niet met, index b.
- woordenboek (dictionary)
- Een verzameling paren sleutel: waarde, waarin je een waarde opzoekt met haar sleutel.
- CSV
- Comma-separated values: een tabel als tekstbestand, één rij per regel, de kolommen gescheiden door een komma.
- ontbrekende waarde
- Een lege cel in een databestand: de meting ontbreekt en mag niet als nul meetellen.
- matplotlib
- Een Python-bibliotheek om grafieken te tekenen: lijnen, staven, puntenwolken.