Tilbake
2.2

2.2 Funksjonssamarbeid og scope

Hvordan funksjoner samarbeider, og reglene for **scope**: en lokal variabel i en funksjon endrer ikke en variabel utenfor — grunnlaget for scope-spørsmålene i Oppgave 2.

40 min
6 oppgaver
Funksjonssamarbeidscope
Din fremgang i kapitlet
0 / 6 oppgaver

Forkunnskaper — sist du var her

Kap. 2.1 — Funksjoner: def, parametere og return.

De tre tingene du trenger derfra:

- at en funksjon defineres én gang og kalles så mange ganger du vil,
- at parameteren er navnet i definisjonen og argumentet er verdien som
sendes inn,
- at return avslutter funksjonen og gir en verdi tilbake — og at en funksjon
uten return gir None.

Kort oppfrisket:

def dobbel(tall):
    return tall * 2

svar = dobbel(21)
print(svar)

Utskrift:

42

Spørsmålet i dette kapitlet er hva som skjer med navnene: hva heter tall utenfor funksjonen, og hva skjer om du tilordner et navn som allerede finnes utenfor?

Løkke 1 — Lokale variabler (~12 min)

Et program kan ha mange variabler med samme navn uten at de kolliderer, fordi hver funksjon har sitt eget lille rom av navn.

Det rommet heter et scope, og reglene for det er få — men de er kilden til et av de mest testede flervalgsspørsmålene på eksamen.

Scope

Området i programmet der et variabelnavn er synlig og kan brukes.

I IN1000 trenger du bare to nivåer:

- Lokalt scope — inne i en funksjon. Alt som lages der, finnes bare mens
funksjonen kjører.
- Globalt scope — utenfor alle funksjoner, altså i hovedprogrammet.

Regelen som avgjør alle spørsmålene: en funksjon kan lese navn fra det globale scopet, men en tilordning inne i funksjonen lager alltid et nytt, lokalt navn.

Ordet uttales «skoup» og betyr rett og slett «virkeområde». Du møter det i oppgavetekster på eksamen, så det er verdt å kjenne igjen.

Lokal variabel

En variabel som lages ved en tilordning inne i en funksjon. Den finnes bare mens funksjonen kjører, og forsvinner når den returnerer:

def regn():
    mellomsvar = 10 * 3 return mellomsvar

print(regn())

Utskrift:

30

Prøver du å bruke mellomsvar etter kallet, får du `NameError: name
'mellomsvar' is not defined` — navnet finnes ikke lenger.

Det er en fordel, ikke en begrensning: derfor kan du bruke i, total og
antall i hver eneste funksjon uten at de kolliderer med hverandre.

Parametere er lokale

En parameter er en helt vanlig lokal variabel. Den får verdien sin fra argumentet, og den forsvinner når funksjonen returnerer:

def dobbel(tall):
    tall = tall * 2 return tall

x = 5 print(dobbel(x), x)

Utskrift:

10 5

Legg merke til at x er uendret. Funksjonen fikk verdien 5 inn i sin egen lokale tall, og endret den lokale kopien.

Dette gjelder for tall, tekst og boolske verdier — altså alt du har møtt så langt. I kap. 5.4 møter du datatyper der bildet er mer sammensatt, og det er nettopp det Oppgave 2 tester.

✏️Eksempel 1: Fire navn som ser like ut

Programmet har antall fire steder. Hvilke av dem er samme variabel, og hva skriver programmet ut?

antall = 100

def tell_opp(antall):
    antall = antall + 1 return antall

def vis():
    print("inne i vis:", antall)

print(tell_opp(5))
vis()
print(antall)

Gå gjennom navnene ett scope om gangen.

StedHvilken antall?
Linje 1den globale — verdien 100
Parameteren i tell_oppen lokal, får verdien 5 fra argumentet
Tilordningen inne i tell_oppsamme lokale, blir 6
Inne i visingen lokal finnes, så den leser den globale

Utskrift:
6 inne i vis: 100
100
Tre poenger:
- tell_opp(5) returnerer 6 og lot den globale være i fred.
- vis leser den globale uten problemer, fordi den ikke tilordner noe med

det navnet. En funksjon kan altså se ut i det globale scopet.
- Etter alt sammen er den globale fortsatt 100.

Slik ville sensor sett på det: dette er nøyaktig formen på et

flervalgsspørsmål i Oppgave 2. Det du blir bedt om, er å avgjøre om utsiden ble endret — og svaret er nesten alltid nei.

📝Oppgave 1

(Innstegsoppgave — ren gjengivelse.) Se på dette programmet:

poeng = 10

def endre():
    poeng = 99 return poeng

a) Hva returnerer kallet endre()?

b) Hvilken verdi har poeng i hovedprogrammet etter kallet?

c) Hvor mange variabler ved navn poeng finnes det i programmet?

Løkke 2 — Å lese ut, og hvorfor return er svaret (~12 min)

En funksjon kan lese en global variabel den ikke selv tilordner. Det høres praktisk ut, og av og til er det det — men det er også en felle du skal styre unna på eksamen.

Global variabel

En variabel som er laget utenfor alle funksjoner, i selve hovedprogrammet.

Den kan leses fra innsiden av en funksjon:

mva = 0.25

def med_mva(pris):
    return pris + pris * mva

print(med_mva(100))

Utskrift:

125.0

Funksjonen fant mva i det globale scopet fordi den ikke har noen lokal variabel med det navnet.

Det virker — men det gjør funksjonen avhengig av noe som står langt unna. Endrer noen mva et helt annet sted i programmet, endres oppførselen til funksjonen uten at kallet ser annerledes ut.

Hvorfor globale variabler unngås

Tre grunner, i den rekkefølgen de betyr noe på eksamen:

1. Funksjonen blir umulig å lese alene. Du må lete i hele programmet for å
vite hva den gjør.
2. Den blir umulig å gjenbruke. En funksjon som henter data fra utsiden, kan
ikke kalles med andre data.
3. Den blir umulig å teste. Du kan ikke gi den nye verdier uten å endre
programmet rundt.

Regelen i faget: alt en funksjon trenger, kommer inn som parameter, og
alt den produserer, går ut som returverdi. Det er den formen sensor forventer, og den formen alle fasitene har.

I kap. 5.1 får du den ordentlige løsningen på «data som skal leve videre»: å legge dem i et objekt i stedet for i en global variabel.

📜Parameter inn, returverdi ut

Bokas fjerde kodemønster, og den korteste regelen i hele boka:

Alt en funksjon trenger, tar den inn som parameter. Alt den gir fra seg, går ut
gjennom return.

def med_mva(pris, sats):
    return pris + pris * sats

print(med_mva(100, 0.25))
print(med_mva(100, 0.15))

Utskrift:

125.0
115.0

Sammenlign med versjonen over, som hentet satsen fra en global variabel. Denne kan kalles med hvilken sats som helst, den kan leses alene, og den gjør nøyaktig det navnet sier.

Mønsteret er selve grunnformen for hver eneste funksjon i Oppgave 3 og hver metode i Oppgave 4.

✏️Eksempel 2: Fra global variabel til parameter

En student har skrevet en funksjon som teller hvor mange tegn i en tekst som er lik et bestemt tegn — men både teksten og tegnet er globale variabler. Vis hvorfor det er upraktisk, og skriv den om.

tekst = "bibliotek" sok = "b"

def tell():
    antall = 0 for t in tekst:
        if t == sok:
            antall = antall + 1 return antall

print(tell())

Koden over kjører, og gir riktig svar:

Utskrift:

2

Problemet vises først når du vil telle noe annet. Funksjonen tar ingen argumenter, så det eneste du kan gjøre, er å endre de globale variablene før hvert kall — og da må hovedprogrammet vite hvilke navn funksjonen bruker innvendig.

Slik skrives den om:

def tell(tekst, sok):
    antall = 0 for t in tekst:
        if t == sok:
            antall = antall + 1 return antall

print(tell("bibliotek", "b"))
print(tell("bibliotek", "i"))
print(tell("kantine", "n"))

Utskrift:

2
2
2

Nå kan den kalles med hva som helst, og kroppen er ord for ord den samme.

Slik ville sensor sett på det: en funksjon som henter data fra globale
variabler i stedet for å ta dem inn som parametere, får sjelden full uttelling — selv om den gir riktig svar for det ene tilfellet oppgaven nevner. Det er
gjenbrukbarheten som er poenget med å skrive en funksjon i det hele tatt.

📝Oppgave 2
Eksamensnivå, sjanger A

Hva skriver programmet ut?

n = 3

def les():
    return n * 2

def skriv_over():
    n = 100 return n

print(les())
print(skriv_over())
print(les())
print(n)

📝Oppgave 3
Eksamensnivå, sjanger C

En funksjon skal regne ut hvor mye et beløp blir med et påslag. Denne versjonen bruker en global variabel:

sats = 0.10

def med_paaslag(belop):
    return belop + belop * sats

a) Skriv om funksjonen så den tar satsen inn som parameter.

b) Vis to kall med ulik sats.

c) Nevn én konkret grunn til at den omskrevne versjonen er bedre.

Løkke 3 — Scope i sporingsoppgaver (~10 min)

Nå er reglene på plass. Det som gjenstår, er å bli rask på å bruke dem i en sporingsoppgave — for det er nettopp den formen Oppgave 2 har.

Å skygge et navn

Når en funksjon lager en lokal variabel med samme navn som en global, sier vi at den skygger den globale: inne i funksjonen er det bare den lokale som er synlig.

farge = "rod"

def vis():
    farge = "bla" print("inne:", farge)

vis()
print("ute:", farge)

Utskrift:

inne: bla ute: rod

Skyggingen varer bare mens funksjonen kjører. Etterpå er den globale like uberørt som før.

Merk at skyggingen gjelder for hele funksjonen, ikke bare fra tilordningen og nedover — prøver du å lese navnet på en linje før tilordningen i samme funksjon, får du en feilmelding i stedet for den globale verdien.

Å lese kontra å tilordne

Den ene regelen du trenger for å svare på alle scope-spørsmål:

Hva funksjonen gjørHvilken variabel treffes
bare leser navnetden globale, hvis ingen lokal finnes
tilordner navnet (med =)en ny lokal, alltid

Det finnes en måte å endre en global variabel fra innsiden på, men den brukes ikke i dette faget og ikke i fasitene — riktig løsning er alltid return.
Sjekklista i en sporingsoppgave er derfor kort: let etter likhetstegn inne i funksjonen. Finner du ett, er navnet lokalt.

Kall endrer ikke argumentet

Sender du et tall, en tekst eller en boolsk verdi inn i en funksjon, kan funksjonen ikke endre variabelen du sendte inn:

def nullstill(verdi):
    verdi = 0 return verdi

poeng = 42 nullstill(poeng)
print(poeng)

Utskrift:

42

Kallet gjorde ingenting synlig utenfra, fordi returverdien ble kastet og parameteren var lokal.

Legg merke til at dette er en stille feil: programmet krasjer ikke, det gjør bare ingenting. Riktig form er poeng = nullstill(poeng).

Bildet blir mer sammensatt for datatypene i kap. 3.1 og
kap. 5.4, og det er nettopp den forskjellen Oppgave 2 er bygget rundt.

✏️Eksempel 3: Et fullt Oppgave-2-mønster, sporet

Dette er på formen et flervalgsspørsmål i Oppgave 2 har. Hva skriver programmet ut?

teller = 0

def opp():
    teller = 1 return teller

def opp_riktig(teller):
    return teller + 1

print(opp())
print(teller)
teller = opp_riktig(teller)
print(teller)

Tre steg, og forskjellen mellom dem er hele poenget.

StegHva som skjerGlobal teller etterpå
opp()lager en lokal teller lik 1 og returnerer den0 — uendret
print(teller)leser den globale0
teller = opp_riktig(teller)sender verdien inn, tar returverdien imot1

Utskrift:
1
0
1
Legg merke til den avgjørende linja. opp_riktig endrer heller ikke noe av
seg selv — den bare returnerer en ny verdi. Det som gjør at den globale oppdateres, er at hovedprogrammet tar imot returverdien med

teller = ....
Det er hele oppskriften: parameter inn, returverdi ut, og ta imot svaret.

Slik ville sensor sett på det: kandidater som svarer at opp() setter den
globale til 1, har gått i felle #12. Kandidater som ser at opp() ikke endrer noe, men glemmer at siste linje faktisk gjør det, har forstått halve mekanismen — og får uttelling for det.

📝Oppgave 4
Eksamensnivå, sjanger A

Hva skriver programmet ut?

navn = "Ada"

def endre(navn):
    navn = navn + "!" return navn

print(endre(navn))
print(navn)
navn = endre(navn)
print(navn)

📝Oppgave 5
Eksamensnivå, sjanger A

Hva skriver programmet ut?

x = 2 y = 3

def f(x):
    y = x * 2 return y

def g():
    return x + y

print(f(10))
print(g())
print(x, y)

📝Oppgave 6
Eksamensnivå, sjanger I

En student skal skrive et program som teller opp en poengsum tre ganger. Hun leverer:

poeng = 0

def legg_til(antall):
    poeng = poeng + antall

legg_til(5)
legg_til(3)

a) Hva skjer når programmet kjøres?

b) Forklar i én setning hvorfor.

c) Rett feilen uten å bruke globale variabler.

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.

`NameError`

Feilmeldingen du får når du bruker et navn Python ikke kjenner.

De to vanligste årsakene i dette faget: du bruker en lokal variabel utenfor funksjonen den ble laget i, eller du kaller en funksjon før def-linja er lest.

Meldingen sier hvilket navn det gjelder — name 'mellomsvar' is not defined — og den er derfor en av de greieste feilene å rette.

`UnboundLocalError`

Feilmeldingen du får når en funksjon leser et navn den også tilordner et sted i kroppen, før tilordningen har skjedd.

Årsaken er at ett likhetstegn gjør navnet lokalt i hele funksjonen — ikke bare fra og med den linja. Funksjonen ser derfor aldri etter den globale variabelen i det hele tatt.

Typisk oppskrift på feilen: poeng = poeng + antall inne i en funksjon der
poeng er ment å være den globale. Løsningen er alltid parameter inn, returverdi ut.

Å ta imot en returverdi

Å skrive x = f(x) i stedet for bare f(x).

Dette er den ene linja som skiller «funksjonen regnet ut noe» fra «programmet husker det». Uten likhetstegnet blir returverdien regnet ut og kastet, og ingenting utenfor funksjonen endres.

Det er en stille feil: programmet krasjer ikke, det gjør bare ingenting. Se etter den hver gang et program «ser riktig ut», men verdiene aldri endrer seg.

Selvstendig funksjon

En funksjon som klarer seg med det den får inn, og som ikke er avhengig av noe utenfor seg selv.

Kjennetegnet: du kan lese den alene og vite nøyaktig hva den gjør, og du kan kalle den med hvilke som helst gyldige data.

Dette er standarden i fagets løsningsforslag, og målestokken sensor bruker. En funksjon som henter data fra globale variabler, gir sjelden full uttelling selv om den svarer riktig på det ene tilfellet i oppgaven.

Hovedprogrammet

Linjene som står uten innrykk og utenfor alle def-blokker. Det er dette
Python kjører ovenfra og ned når du starter programmet.

Variabler laget her lever i det globale scopet, og de finnes så lenge programmet kjører.

I fagets løsningsforslag står alle def-ene øverst og hovedprogrammet nederst.
Det er den formen du bør bruke på eksamen — og du skal ikke pakke det inn i noen egen startfunksjon.

Argumentet er en verdi, ikke en variabel

Når du skriver dobbel(x), er det verdien til x som sendes inn, ikke navnet x.

Funksjonen får aldri vite hva variabelen din het, og den kan derfor ikke endre den. Skriver du dobbel(5) i stedet, oppfører funksjonen seg nøyaktig likt.

Denne presiseringen er det som gjør scope-regelen forståelig i stedet for bare noe å pugge — og den er det Oppgave 2 tester i mer sammensatt form når objektene kommer i kap. 5.4.

To variabler med samme navn

Helt lovlig, så lenge de lever i hvert sitt scope. Programmet kan ha én global
antall og en lokal antall i hver eneste funksjon.

Det er derfor du trygt kan bruke i, total og antall overalt uten å sjekke hva de heter andre steder.

Når du sporer: skriv opp navnene per funksjon, ikke per program. Da faller scope-spørsmålene på plass av seg selv.

Sidevirkning

Noe en funksjon gjør utover å returnere en verdi — for eksempel å skrive til skjermen eller endre noe utenfor seg selv.

I dette faget skal funksjoner helst være fri for sidevirkninger: de tar imot, regner ut og returnerer. Unntaket er metoder som med vilje endrer objektet sitt, og som du møter i kap. 5.2.

Ordet er verdt å kjenne fordi det forklarer hvorfor print inne i en funksjon sjelden er det oppgaven ber om: utskrift er en sidevirkning, ikke et svar.

Ren beregning

En funksjon som bare bruker det den får inn, og bare gir fra seg en returverdi.

Kjennetegnet er at samme argumenter alltid gir samme svar, uansett hva som ellers har skjedd i programmet. med_paaslag(200, 0.10) gir 220 hver eneste gang.

Dette er standardformen for alle funksjonene i Oppgave 3, og den formen som er lettest å få full uttelling for: sensor kan lese funksjonen alene og se at den er riktig.

Scope-sjekklista

Tre spørsmål som avgjør ethvert scope-spørsmål på eksamen, i denne rekkefølgen:

1. Finnes det et likhetstegn med dette navnet inne i funksjonen? Hvis ja, er
navnet lokalt i hele kroppen.
2. Er navnet en parameter? Da er det også lokalt.
3. Ellers: funksjonen leser den globale.

Deretter det avgjørende oppfølgingsspørsmålet: tok hovedprogrammet imot returverdien med et likhetstegn? Hvis ikke, er ingenting endret utenfor.

Repetisjon — de seks 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.