Computers raken niet verveeld. Als een computer een taak honderdduizenden malen moet herhalen, protesteert hij niet. Mensen daarentegen houden niet van teveel herhaling. Daarom moeten herhalende taken aan een computer worden overgelaten. Alle programmeertalen ondersteunen herhalingen. In computertaal benoemen we herhalingen met “iteraties” (Het werkwoord dat in computertaal wordt gebruikt in plaats van herhalen, is “itereren”.), maar een nog vaker gebruikte term is “loops”, wat je netjes kunt vertalen als “lussen”, maar dat zeggen programmeurs nooit. Loops vormen samen met conditionele statements vaak de basis van om het even welk computerprogramma.
Tot nu toe, wanneer we een actie meerdere keren wilden herhalen, gingen we kopiëren en plakken. Bijvoorbeeld:
num = 1
print( num**2,end=' ' )
num = num + 1 # num wordt nu 2
print( num**2,end=' ' )
num = num + 1 # num wordt nu 3
print( num**2,end=' ' )
num = num + 1 # num wordt nu 4
print( num**2,end=' ' )
print( "Klaar" )
Waarom is deze code niet goed? Het geeft toch het gewenste resultaat 1 4 9 16 Klaar
?
Wel, in onze code hebben we gekopiëerd en geplakt.
En er is een heel belangrijke redenen om ten allen tijde kopie-plakken in programmeercode te vermijden: uitbreidbaar.
Willen we de code doen werken voor een ander aantal getallen, bijvoorbeeld alle kwadraten van 1 tot en met 10 (dus met resultaat 1 4 9 16 25 36 49 64 81 100 Klaar
), moeten we opnieuw aan onze code prutsen.
Vijf keer kopie-plakken houden we dat wel vol, tien keer misschien ook, maar bij duizend keer geven we het op.
Vanaf nu zullen we nooit meer kopiëren en plakken in onze code. In het begin wordt dit even wennen.
Waarschijnlijk zul je jezelf er zelfs op betrappen het toch nog te doen. Geen erg - zolang je maar snel genoeg tot inkeer komt.
Normaal start ik het hoofdstuk over herhaling met de while loop, omdat die dichter aanleunt bij de syntax van condities uit vorig hoofdstuk. Toch probeer ik het dit jaar eens andersom. De reden hiervoor is eenvoudig: FOR loops hebben een gemakkelijkere syntax en zijn veiliger te gebruiken dan while loops. Toch worden ze soms gezien als ondergeschikt omdat for loops niet voor alle iteratie problemen gebruikt kunnen worden, terwijl while loops een generieke oplossing bieden voor iteratie problemen. Met andere woorden, alles wat een for loop kan doen, kan een while loop ook doen, maar niet andersom.
for
loopDe schematische syntax voor de for
loop is:
for dummie in lijst:
acties
Een dummie, ook wel wegwerpvariabele doet enkel dienst binnen de for
loop, maar heeft verder nergens in het programma een betekenis.
Vaak wordt als dummie i gekozen. Binnen de loop treedt de dummie op als iterator, die één voor één de elementen van de lijst overloopt (itereert).
Voor elk van de elementen worden de bijhorende acties uitgevoerd.
Let vooral op de gelijkaardige syntax als bij de if
(en straks de while
) statements: zowel de if
, while
en for
lijn wordt telkens afgesloten met een dubbelpunt met daaropvolgend een insprong die alle acties netjes uitlijnt.
Hierboven beschreef ik de algemene syntax voor de for
loop waarbij een dummie itereert over een lijst.
Deze situatie komt met voorsprong meest voor, maar de dummie kan in sommige gevallen ook over een variabele van een ander datatype itereren.
Voorbeelden hiervan zullen we zien in de oefeningen. Eerst meer over itereren over een lijst.
For
loop over een handmatige lijstStartend van een lijst die we handmatig hebben aangemaakt, kunnen we de for
loop gebruiken om acties uit te voeren op elk element van de lijst afzonderlijk. Zo kunnen we uit een lijst elk element afzonderlijk printen, elk element op een nieuwe lijn:
tienmachten = [10,100,1000,10000]
for i in tienmachten:
print( i )
Of:
fruit = ["appel", "peer", "druif", "banaan", "mango", "kers"]
for i in fruit:
print( i )
In beide voorbeelden wordt eerst een lijst aangemaakt en opgeslagen in een variabele (respectievelijk tienmachten en fruit genaamd). Wanneer we aan de for loop starten, weten we dus hoeveel keer die zal worden doorlopen. De lijst tienmachten bevat vier elementen, de actie in de for loop zal dus vier keer worden uitgevoerd. De lijst fruit bevat zes elementen, dus de actie in de for loop zal zes keer worden uitgevoerd. Bij een for loop wordt altijd van bij het begin gespecifiëerd wanneer de loop zal eindigen, via het aantal elementen in de lijst.
De dummie i wordt in beide voorbeelden slechts gebruikt om te printen, maar zijn waarde kan ook perfect binnen een expressie gebruikt worden (houd dan wel goed het datatype indachtig!), bijvoorbeeld:
exponenten = [1,2,3,4]
for i in exponenten:
tienmacht = 10**i
print( tienmacht )
range()
functieSoms is het aantal elementen over dewelke we willen itereren veel groter dan vier of zes. Dan zouden ook de lijsten veel langer moeten worden, wat ons heel wat werk kan opleveren. In sommige gevallen kunnen we zulke lijsten automatisch genereren. In het bijzonder lijsten met getallen waarin we een patroon kunnen herkennen.
Het gekendste voorbeeld is de lijst [0,1,2,3,4,5,…,n], met n+1 elementen.
(Dat de lijst n+1 elementen bevat en niet n, is een gevolg van het feit dat we beginnen tellen vanaf 0, typisch aan vele computertalen, ook Python).
Zo’n lijst opstellen voor 0 tot en met 99 is heel wat werk. Dat kan efficiënter.
Inderdaad, Python heeft een functie range()
die het mogelijk maakt een lijst opeenvolgende getallen te genereren.
De range()
functie verlangt minstens één argument:
range()
, dan maakt de functie een lijst opeenvolgende getallen aan startend bij 0 en eindigend bij het gegeven getal-1.
Zo zijn volgende lijsten identiek:
manuele_lijst = [0,1,2,3,4,5,6,7,8,9]
automatische_lijst = range( 10 )
(Hoewel beide lijsten identiek zijn, zal een ervaren programmeur nooit de manuele lijst opstellen.
De range()
functie spaart wat typ-werk, maar belangrijker, bij de automatisch gegenereerde lijst is er opnieuw sprake van ‘veralgemeenbaarheid’.
Wil iemand de code aanpassen voor 100 in plaats van 10 elementen? Geen probleem - toch niet voor de automatische lijst.)
range()
functie meegeven, dan kunnen we met het eerste argument ook het startgetal bepalen.
Het tweede argument wordt opnieuw het eindgetal-1. Zo zijn volgende lijsten identiek:
manuele_lijst = [4,5,6,7,8,9]
automatische_lijst = range( 4,10 )
range()
functie, dan wordt die geïnterpreteerd als de stapgrootte.
Opnieuw zijn volgende lijsten identiek:
manuele_lijst = [4,6,8,10,12,14]
automatische_lijst = range( 4,15,2 )
Later zullen we nog veel andere mogelijkheden zien om lijsten automatisch te genereren, niet enkel met de range()
functie.
Toch bekijken we de functie range()
hier al, net omdat deze zo vaak gebruikt wordt in combinatie met een for loop.
Tot slot keren we terug op het inleidend voorbeeld dat een reeks volkomen kwadraten op ons scherm laat verschijnen. Ik deed al enkele voorstellen, maar keurde ze telkens af. Hier dan eindelijk een propere oplossing:
N = 5
for num in range( 1,N+1 ):
print( num**2 ,end=' ' )
print( "Enzovoort" )