Løkker lar oss gjenta arbeid uten å skrive samme kode mange ganger. En while-løkke kjører så lenge en betingelse holder, mens en for-løkke går gjennom en sekvens, ofte med range. Vi bruker akkumulatorvariabler og styrer flyten med break og continue.
Læringsmål
01Forklare forskjellen på while- og for-løkker og velge riktig løkke ut fra om antall iterasjoner er kjent på forhånd
02Bruke range med start, stopp og steg, og forklare hvorfor stoppverdien er eksklusiv
03Skrive en akkumulator-løkke som bygger opp en sum eller et produkt, og forklare hvorfor startverdien settes utenfor løkka
04Bruke break og continue korrekt, og spore variabelverdier gjennom iterasjonene i en sporingstabell
Tenk deg at du skal skrive ut tallene fra 1 til 100. Du kan skrive hundre print-setninger under hverandre, men det er både slitsomt og lett å bomme på. Et program skal nettopp slippe deg unna slik gjentakelse. Verktøyet heter løkke: en blokk med kode som kjøres flere ganger, styrt av en betingelse eller en samling vi går gjennom.
Python har to løkketyper, og de svarer på to ulike spørsmål. Spørsmålet «så lenge noe er sant, fortsett» besvares av while-løkke. Spørsmålet «for hvert element i denne samlingen, gjør noe» besvares av for-løkke. Begge utfører den samme indenterte blokken på nytt og på nytt, men de bestemmer på hver sin måte når de skal stoppe.
Det er verdt å se selve formen i et diagram før vi graver i koden. Hver runde gjennom løkka kaller vi en iterasjon, og det avgjørende er tilbake-pilen: når blokken er ferdig, hopper kjøringen opp igjen og sjekker betingelsen på nytt.
FIGwhile-løkke med tilbake-pil
while — gjenta så lenge betingelsen holder
En while-løkke består av nøkkelordet while, et logisk uttrykk, kolon, og en indentert blokk. Så lenge uttrykket er sant, kjøres blokken; idet det blir usant, hopper vi forbi blokken og fortsetter under løkka.
Her starter tall på 1. Betingelsen tall <= 5 er sann, så vi skriver ut og øker tall. Dette gjentas til tall blir 6, betingelsen blir usann, og løkka avsluttes. Legg merke til linja tall = tall + 1: uten den ville tall blitt værende 1 for alltid, betingelsen alltid være sann, og programmet henge i en uendelig løkke. Den klassiske while-feilen er nettopp å glemme å endre variabelen betingelsen hviler på.
Det hjelper å spore variablene runde for runde. En slik sporingstabell viser én rad per iterasjon, og gjør det synlig akkurat når betingelsen velter.
FIGSporing av tall gjennom iterasjonene
while egner seg best når du ikke vet på forhånd hvor mange runder du trenger. Tenk på «les inn tall fra brukeren helt til de skriver 0», eller «fortsett å gjette til du treffer». Antall runder bestemmes underveis, av data du ikke kjenner når du skriver koden.
Et nært beslektet mønster er den såkalte vakt-verdien (engelsk sentinel): du leser inn verdier i en while-løkke helt til brukeren oppgir en avtalt stoppverdi. Da må du lese den første verdien før løkka, sjekke den i betingelsen, og lese neste verdi nederst i blokken — ellers behandler du stoppverdien som om den var ekte data. Dette «les én før, les neste sist»-mønsteret går igjen så ofte at det er verdt å kjenne igjen.
python
sum_av_tall = 0tall = int(input("tall (0 for å stoppe): "))
whiletall != 0:
sum_av_tall = sum_av_tall + talltall = int(input("tall (0 for å stoppe): "))
print("summen ble", sum_av_tall)
Legg merke til at 0 aldri legges til summen — den brukes kun som signal om at vi er ferdige. Akkurat denne plasseringen av de to input-linjene er den vanligste kilden til feil i while-løkker som leser data.
for — gå gjennom en samling
Når du derimot vet nøyaktig hva du skal gå gjennom, er for ryddigere. En for-løkke tar en variabel og en samling, og kjører blokken én gang for hvert element, med variabelen satt til elementet.
python
forbokstavin"kake":
print(bokstav)
Dette skriver ut k, a, k, e — én per linje. Variabelen bokstav peker på et nytt tegn for hver runde. Du kan gå gjennom strenger, lister, og alt annet som er itererbart.
Når du vil løkke et bestemt antall ganger, bruker du range. range(n) produserer tallene fra 0 til og med n - 1. Det fanger nye nybegynnere på senga: range(5) gir 0, 1, 2, 3, 4, altså fem tall, men ikke tallet 5. Slutten er eksklusiv.
FIGrange(5) treffer 0..4, ikke 5
range har tre former. range(stopp) starter på 0. range(start, stopp) lar deg velge startpunkt. range(start, stopp, steg) lar deg hoppe — range(0, 10, 2) gir partallene 0, 2, 4, 6, 8. Et negativt steg teller nedover: range(5, 0, -1) gir 5, 4, 3, 2, 1.
python
foriinrange(1, 6):
print(i, "i andre er", i * i)
Her er i et tall vi både skriver ut og regner med. Mønsteret «for i in range(...)» er trolig den vanligste løkka du kommer til å skrive.
Akkumulator — å bygge opp et svar
Det aller viktigste løkkemønsteret er akkumulator: en variabel som settes opp før løkka og oppdateres inne i løkka, slik at den til slutt holder summen, produktet eller listen du var ute etter. Poenget er at startverdien settes utenfor — ellers nullstilles den hver runde.
akkumulator
Akkumulator: summer en liste med tall
python
1tall_liste = [4, 8, 15, 16, 23, 42]2total = 0# startverdi UTENFOR løkka3fortallintall_liste:4total = total + tall# oppdater hver runde5print("summen er", total) # -> summen er 108
Klassisk akkumulator-mønster: total settes til 0 før løkka og bygges opp ett element om gangen. Bytter du startverdi til 1 og + til *, regner samme skjelett ut et produkt.
Mønsteret er alltid det samme. Sett opp en startverdi (0 for sum, 1 for produkt, tom streng eller tom liste for samling). Løkk gjennom dataene. Oppdater akkumulatoren med det aktuelle elementet. Etter løkka er svaret klart. Skifter du total = total + tall ut med total = total * tall og starter på 1, regner samme skjelett ut et produkt i stedet.
break og continue — bryte mønsteret
Av og til vil du ut av løkka før betingelsen normalt ville stoppet den. break avbryter løkka umiddelbart og hopper til koden under. Det er nyttig når du leter etter noe og finner det: du trenger ikke fortsette å lete.
python
fortallinrange(2, 100):
iftall * tall > 50:
print("første kvadrat over 50 kommer fra", tall)
break
Søsteret er continue, som hopper over resten av den nåværende runden og går rett til neste iterasjon. Betingelsen sjekkes på nytt, løkka lever videre — bare denne ene runden ble kuttet kort.
Her hopper continue over alle partall, slik at bare oddetallene skrives ut. Du kunne oppnådd det samme med en if rundt print, og ofte er det klarere. Bruk continue når det å «hoppe over» er det naturlige å si.
Løkker inni løkker
En løkke kan ligge inne i en annen. Den indre løkka kjører helt ferdig for hver eneste runde i den ytre. Det er slik du jobber deg gjennom et rutenett, en gangetabell eller alle par av elementer.
Den ytre løkka kjører tre ganger; for hver av dem kjører den indre tre ganger. Til sammen ni utskrifter — en liten 3×3-gangetabell. Pass på indenteringen: alt som skal være inni den indre løkka, må rykkes inn ett hakk til, og print() på slutten ligger på den ytre løkkas nivå slik at vi får et linjeskift etter hver rad. Nøstede løkker er kraftige, men koster: to nøstede løkker over n elementer gjør n ganger n arbeid, og det vokser fort. Skal du sammenligne alle par i en liste på tusen elementer, snakker vi en million sammenligninger — noe å være bevisst på når programmet plutselig går tregt.
Et break inne i en nøstet løkke bryter bare ut av den løkka det står i, ikke alle. Vil du ut av begge, må du enten bryte den indre og så sjekke en flagg-variabel i den ytre, eller — ofte renere — pakke det hele inn i en funksjon og bruke return, som du møter i neste kapittel.
Hvilken løkke velger jeg
Tommelfingerregelen er enkel. Vet du hva du går gjennom, eller hvor mange ganger? Bruk for, gjerne med range. Avhenger antall runder av noe som skjer underveis — brukerinndata, en beregning som skal konvergere, en fil du leser til den tar slutt? Bruk while. Begge kan i prinsippet erstatte hverandre, men koden blir lesbar når du velger den som matcher problemet. Og uansett hvilken du velger: sørg for at noe faktisk endrer seg mot et stoppunkt for hver runde, ellers står programmet og maler.
Mine notater
Skriv egne notater for dette kapittelet. De lagres automatisk og dukker opp i «Mine notater»-oversikten paa fag-siden.