Tilbake
1.3

1.3 Løkker: for, while og range

`for`-løkker over sekvenser og `range`, `while`-løkker, nøstede løkker og akkumulatormønsteret — den vanligste kodesporingskilden og motoren i all kodeskriving.

50 min
8 oppgaver
Løkkerforwhilerange
Din fremgang i kapitlet
0 / 8 oppgaver

Forkunnskaper — sist du var her

Kap. 1.1 — Variabler, datatyper og uttrykk og
kap. 1.2 — Betingelser og boolske uttrykk. Du trenger derfra:

- at en tilordning regner ut høyre side først og deretter lar navnet peke på
resultatet — det avgjør alt som skjer inne i en løkke,
- at innrykk bestemmer hvilke linjer som hører til en blokk,
- at en betingelse gir True eller False,
- de sju regneoperatorene, særlig % og //.

Kort oppfrisket, de to tingene du bruker mest her:

total = 0 total = total + 6 if total % 2 == 0:
    print("partall", total)

Utskrift:

partall 6

Legg merke til de to stegene: tilordningen bygger opp en verdi, og betingelsen avgjør om noe skjer. Nettopp de to stegene er byggeklossene i hele dette kapitlet.

Løkke 1 — for og range (~12 min)

En skoleklasse skal betale for en tur. Du vil skrive «Deltaker 1», «Deltaker 2»
og så videre helt til «Deltaker 25». Å skrive 25 print-linjer er utenkelig.

Det du trenger, er en løkke: en blokk med kode som kjøres om og om igjen, med en litt ny verdi hver gang.

Løkke

En blokk med kode som kjøres flere ganger. Hver gjennomkjøring kalles en
runde eller en iterasjon.

Python har to løkketyper, og de dekker hver sin situasjon:

- for — når du vet hva du skal gå gjennom: alle tallene fra 1 til 25, alle
tegnene i et navn, alle elementene i en samling.
- while — når du ikke vet hvor mange runder det blir, bare når du skal
stoppe: «så lenge saldoen er positiv».

I praksis dekker for de fleste oppgavene på eksamen. while kommer til sin rett når antallet runder avhenger av noe som skjer underveis.

`for e in sekvens:`

Kjører blokken én gang for hvert element i sekvensen. Variabelen mellom for og
inløkkevariabelen — får en ny verdi for hver runde:

for tegn in "sol":
    print(tegn)

Utskrift:

s o l

Formkravene er de samme som for if: kolon på slutten av linja, og innrykk på linjene som hører til.

Løkkevariabelen er et vanlig variabelnavn du velger selv. Kall den noe som sier hva den inneholder — tegn når det er tegn, tall når det er tall.

`range(stopp)`

Lager tallrekka fra 0 og oppover, men ikke med stoppverdien:

for i in range(4):
    print(i)

Utskrift:

0
1
2
3

Fire runder, med verdiene 0, 1, 2 og 3. Tallet i parentesen er antallet runder, ikke den siste verdien.

At stoppverdien ikke er med, er den mest omtalte detaljen i hele Python, og årsaken til feilkode #5 — av-med-én. Til gjengjeld gir den en enkel regel:
range(N) gir alltid nøyaktig N runder.

`range(start, stopp)`

Tallrekka fra start til og med stopp minus én:

for i in range(2, 6):
    print(i)

Utskrift:

2
3
4
5

Startverdien er med, stoppverdien er ikke. Antall runder er stopp - start, altså fire her.

Vil du telle fra 1 til 25 slik et menneske ville sagt det, skriver du derfor
range(1, 26).

`range(start, stopp, steg)`

Samme som over, men hopper steg om gangen:

for i in range(0, 10, 3):
    print(i)

Utskrift:

0
3
6
9

Neste verdi ville vært 12, som er forbi stoppverdien, så løkka stopper.

Steget kan være negativt, og da teller løkka nedover. Da må startverdien være den største: range(5, 0, -1) gir 5, 4, 3, 2, 1.

Antall runder i en `range`

Regelen du skal kunne uten å telle:

UttrykkVerdierAntall runder
range(4)0, 1, 2, 34
range(2, 6)2, 3, 4, 54
range(0, 10, 3)0, 3, 6, 94
range(0)ingen0
range(3, 3)ingen0

De to siste er verdt et blikk: en range der start og stopp er like, gir ingen runder i det hele tatt, og blokken kjøres aldri. Det er ikke en feil — det er ofte akkurat det du vil ha.

✏️Eksempel 1: Fra 1 til 25, slik et menneske teller

Skriv ut «Deltaker 1» til «Deltaker 5». Hvilken range trenger du, og hva blir utskriften?

Menneskelig telling begynner på 1 og tar med den siste verdien. range begynner på 0 og tar ikke med stoppverdien. Derfor må begge tallene justeres:

for i in range(1, 6):
    print("Deltaker", i)

Utskrift:

Deltaker 1
Deltaker 2
Deltaker 3
Deltaker 4
Deltaker 5

Fem runder, som er 6 - 1.

Slik regner du det ut på eksamen: ta stoppverdien minus startverdien. Vil du
ha verdiene 1 til og med 25, skriver du range(1, 26) og får 25 runder.

Legg merke til at print("Deltaker", i) setter ett mellomrom mellom teksten og tallet, slik du så i kap. 1.1. Her slipper du å konvertere tallet, fordi komma i print tåler alle typer.

📝Oppgave 1

(Innstegsoppgave — ren gjengivelse.) Svar uten å skrive kode.

a) Hvor mange runder gir range(7), og hva er første og siste verdi?

b) Hvor mange runder gir range(3, 9)?

c) Hvilke verdier gir range(0, 8, 2)?

d) Hvor mange runder gir range(5, 5)?

Løkke 2 — Teller og akkumulator (~12 min)

En løkke som bare skriver ut, er sjelden nok. Som regel skal du samle opp noe underveis: hvor mange var det, hva ble summen, hvilken var størst.

To mønstre dekker nesten alt dette, og de er de to første av bokas elleve kodemønstre. De kommer igjen i hver eneste funksjon du skriver resten av faget.

📜Akkumulatormønsteret

Å bygge opp en verdi litt etter litt gjennom en løkke. Tre faste steg:

1. Før løkka: lag variabelen og gi den en startverdi, som regel 0.
2. Inne i løkka: oppdater den med den nye verdien.
3. Etter løkka: bruk resultatet.

total = 0 for i in range(1, 5):
    total = total + i print(total)

Utskrift:

10

Summen av 1, 2, 3 og 4.

Det avgjørende er hvor de tre stegene står. Står total = 0 inne i løkka,
nullstilles den hver runde og svaret blir bare det siste tallet. Står print inne i løkka, får du fire utskrifter i stedet for én. Innrykket er hele forskjellen.

📜Tellermønsteret

Å telle hvor mange ganger noe skjer. Samme tre steg som akkumulatoren, men du legger alltid til 1, og bare når betingelsen er sann:

antall = 0 for i in range(1, 11):
    if i % 3 == 0:
        antall = antall + 1 print(antall)

Utskrift:

3

Tallene 3, 6 og 9 er delelige med 3.

Legg merke til de to nivåene av innrykk: if hører til løkka, og oppdateringen hører til if. Det er dette mønsteret alle «hvor mange
…»-oppgavene på eksamen bruker, og du kan skrive antall += 1 i stedet hvis du vil.

✏️Eksempel 2: Summen og antallet i samme løkke

Gå gjennom tallene fra 1 til 6, og finn både summen av alle og antallet partall. Hvorfor kan begge deler gjøres i samme løkke?

Du trenger to variabler før løkka, og de oppdateres uavhengig av hverandre inne i den:

total = 0 antall_partall = 0 for i in range(1, 7):
    total = total + i if i % 2 == 0:
        antall_partall = antall_partall + 1 print(total, antall_partall)

Utskrift:

21 3

Summen 1 + 2 + 3 + 4 + 5 + 6 er 21, og partallene er 2, 4 og 6.

Tavla, runde for runde:

itotal etterPartall?antall_partall etter
11nei0
23ja1
36nei1
410ja2
515nei2
621ja3

Hvorfor det virker: de to variablene lever hver sitt liv. total oppdateres
hver runde fordi linja står rett under for; antall_partall oppdateres bare når if-en slår til, fordi linja står under if.
Å samle flere ting i én løkke er den vanlige formen på eksamen — det er sjelden verdt å gå gjennom de samme dataene to ganger.

📝Oppgave 2
Eksamensnivå, sjanger A

Hva skriver programmet ut?

total = 0 for i in range(4):
    total = total + i * 2 print(total)

📝Oppgave 3
Eksamensnivå, sjanger…

Skriv et program som teller hvor mange av tallene fra 1 til 20 som er delelige med 4, og skriver ut antallet.

a) Skriv koden.

b) Hva ville skjedd om du satte antall = 0 inne i løkka?

c) Hva ville skjedd om print sto inne i løkka?

Løkke 3 — while (~10 min)

Noen ganger vet du ikke hvor mange runder du trenger. «Halver tallet til det er mindre enn 1.» «Fortsett så lenge saldoen holder.»

Da bruker du en while-løkke, som kjører så lenge en betingelse er sann.

— naturlig pausepunkt —

`while betingelse:`

Kjører blokken om og om igjen så lenge betingelsen er sann. Betingelsen sjekkes
før hver runde:

n = 8 while n > 1:
    print(n)
    n = n // 2 print("ferdig")

Utskrift:

8
4
2 ferdig

Legg merke til at 1 aldri skrives ut: når n er blitt 1, er betingelsen
1 > 1 usann, og løkka avsluttes før neste runde.

Er betingelsen usann allerede første gang, kjøres blokken null ganger. En
while-løkke er altså ikke garantert å kjøre i det hele tatt.

Å endre betingelsesvariabelen

En while-løkke stopper bare hvis noe inne i den gjør betingelsen usann til slutt. Linja som gjør det, er like viktig som selve betingelsen.

I eksempelet over er det n = n // 2. Uten den ville n vært 8 for alltid, og
8 > 1 ville vært sant for alltid.

Vanen som redder deg: når du har skrevet while, finn med én gang linja som
til slutt gjør betingelsen usann, og skriv den før du skriver resten av kroppen.

✏️Eksempel 3: En `while` som endrer to variabler

Dette er en klassisk sporingsoppgave. Hva skriver programmet ut, og hvorfor er rekkefølgen på de to siste linjene i løkka avgjørende?

n = 20 s = 0 while n > 1:
    s = s + n n = n // 2 print(s, n)

Før en tavle. Sjekk betingelsen før hver runde, og oppdater i den rekkefølgen linjene står.

Runden ved startn > 1?s ettern etter
120ja2010
210ja305
35ja352
42ja371
1nei371

Utskrift:
37 1
Hvorfor rekkefølgen avgjør: i hver runde legges den gamle verdien av n
til summen, før n halveres. Byttet du om de to linjene, ville den halverte verdien blitt lagt til i stedet, og svaret blitt 10 + 5 + 2 + 1, altså 18.
Legg også merke til at n er 1 etter løkka, ikke 0. Løkkevariabelen i en
while beholder verdien den hadde da betingelsen sviktet, og den verdien kan du bli spurt om.

📝Oppgave 4
Eksamensnivå, sjanger A

Hva skriver programmet ut?

tall = 1 runder = 0 while tall < 50:
    tall = tall * 3 runder = runder + 1 print(tall, runder)

Løkke 4 — Nøstede løkker (~10 min)

En løkke kan stå inne i en annen. Da kjøres hele den indre løkka på nytt for hver runde i den ytre — og antall runder ganges sammen.

Nøstede løkker er den tyngste sporingssjangeren i Oppgave 1, og de er verdt å øve på til de er mekaniske.

Nøstet løkke

En løkke inne i en annen løkke. Den indre kjøres helt ferdig for hver eneste runde i den ytre:

for i in range(2):
    for j in range(3):
        print(i, j)

Utskrift:

0 0
0 1
0 2
1 0
1 1
1 2

Seks linjer: to ytre runder ganger tre indre.

Regelen for sporing: den indre løkka begynner forfra hver gang. Legg merke
til at j starter på 0 igjen når i blir 1.

Med faste grenser er antallet linjer alltid produktet av de to.

Indre grense som avhenger av den ytre

Den indre range kan bruke den ytre løkkevariabelen. Da blir antall indre runder forskjellig for hver ytre runde:

for i in range(4):
    for j in range(i):
        print(i, j)

Utskrift:

1 0
2 0
2 1
3 0
3 1
3 2

Seks linjer, ikke seksten. Når i er 0, gir range(0) ingen runder i det hele tatt, og den indre løkka kjøres aldri.

Antallet blir 0 + 1 + 2 + 3, altså 6. Dette mønsteret er en fast kilde til sporingsoppgaver nettopp fordi den første ytre runden ikke gir noe utslag.

✏️Eksempel 4: Oppsamling i nøstet løkke med betingelse

Dette er den vanskeligste sporingsformen i Oppgave 1: nøstet løkke, betingelse og akkumulator i samme program. Hva skriver det ut?

total = 0 for i in range(4):
    for j in range(i):
        if j % 2 == 0:
            total = total + 1 print(total)

Bygg tavla én ytre runde om gangen, og noter hvilke j-verdier som finnes.

irange(i) girj-verdier med j % 2 == 0total etter
0ingenting0
1001
20, 102
30, 1, 20, 24

Utskrift:
4
Tre observasjoner som er verdt poeng:
- Den første ytre runden gir ingen indre runder, fordi range(0) er tom.
- Betingelsen filtrerer bort omtrent halvparten av de indre rundene, så antall

oppdateringer er langt lavere enn antall indre runder (som er 0 + 1 + 2 + 3 =
6).

- total overlever mellom de ytre rundene, fordi den er laget før begge

løkkene.
Slik ville sensor sett på det: en kandidat som setter opp riktig tavle men
regner feil på én rad, har vist hele metoden og får god uttelling. Den som svarer 6, har glemt betingelsen; den som svarer 10, har regnet med at
range(i) gir i + 1 runder.

📝Oppgave 5
Eksamensnivå, sjanger A

Hva skriver programmet ut? Skriv utskriften nøyaktig, med linjeskift.

for i in range(1, 4):
    for j in range(2):
        print(i * j)

📝Oppgave 6
Eksamensnivå, sjanger A

Hva skriver programmet ut?

total = 0 for i in range(5):
    for j in range(i):
        total = total + 1 print(total)

Løkke 5 — Rekkefølgen på oppdateringene (~6 min)

Den siste fella i kapitlet er også den mest omtalte i eksamensarkivet, og den handler ikke om løkker i det hele tatt — den handler om tilordning.

Når en løkke oppdaterer to variabler i samme runde, og den ene bruker den andre, avgjør rekkefølgen på linjene hva svaret blir.

Muteringsrekkefølge

Inne i en løkke leses høyre side av en tilordning med de verdiene variablene har
akkurat nå — altså etter alle tidligere linjer i samme runde.

a = 1 b = 2 for i in range(3):
    a = 2 * a + b b = b + 1 print(a, b)

Utskrift:

26 5

Merk at a bruker den gamle b i sin egen linje, fordi b oppdateres etterpå. Byttet du om de to linjene, ville a brukt den nye b, og svaret blitt et helt annet.

Dette er ikke en spissfindighet: det er et fast innslag i Oppgave 1, og fasiten avhenger av at du sporer linjene i den rekkefølgen de står.

✏️Eksempel 5: Samme to linjer, motsatt rekkefølge

De to programmene har de samme fire linjene — bare rekkefølgen inne i løkka er byttet. Hva skriver hvert av dem ut?

a = 1 b = 2 for i in range(3):
    a = 2 * a + b b = b + 1 print("A:", a, b)

a = 1 b = 2 for i in range(3):
    b = b + 1 a = 2 * a + b print("B:", a, b)

Første program, der a regnes først og bruker den gamle b:

Rundea førb føra etterb etter
11243
243114
3114265

Utskrift:
A: 26 5
Andre program, der b økes først og a dermed bruker den nye verdien:
Rundea førb etter økninga etter
1135
25414
314533

Utskrift:

B: 33 5

Samme startverdier, samme antall runder, samme regnestykke — og likevel 26 mot

33. Forskjellen er utelukkende hvilken linje som står først.
Slik sporer du det trygt: skriv én kolonne per variabel, og fyll ut radene i
den rekkefølgen linjene står. Aldri regn to oppdateringer «samtidig».

📝Oppgave 7
Eksamensnivå, sjanger A

Hva skriver programmet ut?

x = 3 y = 1 for i in range(3):
    x = x + y y = x - y print(x, y)

📝Oppgave 8
Eksamensnivå, sjanger A

Hva skriver programmet ut? Skriv utskriften nøyaktig, med linjeskift.

antall = 0 n = 30 while n > 1:
    if n % 2 == 0:
        n = n // 2 else:
        n = n - 1 antall = antall + 1 print(n, antall)

API- og konstruksjonsliste

Begrepsbank

Begrepsbanken er flashcard- og repetisjonsstoff — den gjentar det du nettopp har lest. Hopp trygt over ved førstegangslesing; tidsanslaget for kapitlet gjelder kjernestoffet.

Iterasjon

Én gjennomkjøring av løkkekroppen. En løkke med fire iterasjoner kjører blokken fire ganger.

Ordet brukes også som verb: «å iterere over noe» betyr å gå gjennom det element for element. Du møter det i oppgavetekster og i fasiter, og det betyr aldri noe mer avansert enn dette.

Løkkevariabel

Variabelen som får en ny verdi for hver runde — i i for i in range(5):.

To ting om den. Den lever videre etter løkka, med verdien fra siste runde, og den verdien kan du bli spurt om. Og navnet er ditt eget valg: bruk i for indekser og tellevariabler, og et beskrivende navn ellers.

Kjørte løkka null ganger, finnes variabelen ikke i det hele tatt.

Løkkekropp

Linjene som kjøres hver runde, altså de innrykkede linjene under for eller
while.

Å avgjøre hva som er i kroppen og hva som er utenfor, er første steg i enhver sporing. Startverdier hører utenfor, foran løkka; sluttresultatet skrives ut utenfor, etter løkka.

Negativt steg
range(start, stopp, steg) med negativt steg teller nedover:
range(5, 0, -1) gir 5, 4, 3, 2, 1.

Reglene er de samme som ellers: startverdien er med, stoppverdien er ikke. Med negativt steg må startverdien være størst, ellers blir rekka tom og blokken kjøres aldri.

Gjennomløping av en tekst
for tegn in tekst: går gjennom strengen ett tegn om gangen, fra venstre mot høyre. Løkkevariabelen holder på ett enkelt tegn — altså en streng av lengde én.

Antall runder er antall tegn i teksten, mellomrom medregnet. En tom tekst gir null runder.

Dette er inngangen til alle streng-oppgavene i
kap. 3.3, der du bygger opp en ny tekst tegn for tegn.

Tom sekvens

En sekvens uten elementer: range(0), range(3, 3), eller en tom tekst.

En for-løkke over en tom sekvens kjører blokken null ganger. Det er ikke en feil, og det gir ingen feilmelding — programmet går rett videre til linja etter løkka.

I en sporingsoppgave er dette et fullgodt svar: «løkka kjører aldri, så programmet skriver ingenting».

Uendelig løkke

En while-løkke der betingelsen aldri blir usann. Programmet stopper aldri av seg selv.

Årsaken er nesten alltid den samme: ingen linje inne i løkka endrer variabelen betingelsen spør om. Motmiddelet er å skrive den linja først, før resten av kroppen.

I en sporingsoppgave kan riktig svar være at programmet aldri blir ferdig. Se derfor alltid etter linja som til slutt gjør betingelsen usann.

Sporingstavle

En tabell der du skriver én rad per runde og én kolonne per variabel som endrer seg, pluss en kolonne for hva som er skrevet ut så langt.

Tavla er bokas standardverktøy for sjanger A, og den er grunnen til at du kan løse en nøstet løkke uten å gjette. Den koster et halvt minutt på eksamen og fjerner nesten hele feilrisikoen.

Metoden står i sin fulle form i kap. 4.1.

Antall runder i en nøstet løkke

Med faste grenser ganges antallet: en ytre løkke med 3 runder og en indre med 2 gir 6 gjennomkjøringer av den indre blokken.

Med en indre grense som avhenger av den ytre må du summere i stedet. for i in range(4): for j in range(i): gir 0 + 1 + 2 + 3, altså 6 — ikke 16.

Regn alltid ut antallet før du sporer. Da vet du hvor mange linjer utskrift du skal ende opp med, og du oppdager med én gang om sporingen sklir ut.

Repetisjon — de sju setningene som må sitte

Dette kapitlet er skrevet av Anthropics toppmodeller (Claude Opus og Claude Fable) og er foreløpig ikke manuelt gjennomgått — kvalitetskontrollen gjøres av uavhengige KI-agenter, og innmeldte feil rettes fortløpende. Funnet en feil? Meld fra, så retter vi den. Les mer om hvordan innholdet lages.

Skolesaga er en uavhengig læringsressurs og er ikke tilknyttet eller godkjent av Universitetet i Oslo. Dette er ikke offisielt studiemateriell. Les mer.