2.1 Funksjoner: def, parametere og return
Definere funksjoner, sende parametere, returnere én eller flere verdier — grunnhåndverket alle programmeringsoppgaver hviler på.
- 100 % (10 av 10 sett): hvert eneste sett i arkivet 2014–2019 ber deg skrive funksjoner ut fra en kravbeskrivelse. Programmeringsoppgavene alene teller ~50–60 % av settet.
- De fem oppgavesjangrene E–I er leddene i den samme store oppgaven: E — lese inn data, F — omforme dem, G — analysere dem, H — spørre brukeren eller vise en meny, I — skrive ut eller lagre resultatet. Hvert ledd besvares ved å skrive én funksjon. Uten dette kapitlet har du ingenting å bygge de leddene av.
- Sjanger B — kodesporing, altså «hva skriver dette programmet ut?», har også 100 % frekvens, og et funksjonskall er en av de faste innpakningene: du får en def og et kall, og skal si nøyaktig hva som kommer ut.
- To detaljer går igjen som faste innslag i fasitene: flere returverdier (return a, b) og default-argumenter (def f(pris, prosent=10)).
Prioritet: høyeste — dette må sitte. Vurderingen er én skriftlig skoleeksamen på fire timer som teller 100 %, med hjelpemiddelkode D: bare en bestemt, enkel kalkulator, ingen bøker, ingen notater, ingen annen elektronikk. Du skriver altså funksjonene for hånd, på papir, uten å kunne kjøre dem.
Og en beroligelse før du begynner: karakterskalaen er A–F, og C er en god og vanlig karakter. Sensor gir uttelling for riktig overordnet struktur selv når det står en indeksfeil i koden, og flere korrekte løsninger sidestilles.
Lesetid: kapitlet er seks små løkker på til sammen ~45 minutter. Anslaget er lesetid — skriver du koden selv underveis, som du bør, regn ×1,5.
- kap. 1.1 — variabler, datatyper og konvertering med int(), float() og str().
- kap. 1.2 — sammenligninger, and/or/not og if/elif/else.
- kap. 1.3 — for- og while-løkker, range og akkumulatormønsteret: startverdien settes før løkka, og oppdateres inne i den.
Har du ikke lest dem, er dette det du må ta med deg: range(a, b) gir tallene fra og med a til men ikke med b, og en løkke som skal summere noe, må ha total = 0 stående før løkka.
Lister brukes her bare slik Del 1 bruker dem: som noe du går gjennom med en for-løkke, teller med len(...) og henter ut av med verdier[i]. Selve listeapparatet — append, utsnitt og snarveiene max/sum — kommer i kap. 3.1.
Løkke 1 — Hva en funksjon er (~7 min)
Panteautomaten på butikken gjør én ting: du putter inn flasker, den gir deg en kvittering med et beløp. Du trenger ikke vite hvordan den teller, og du bygger ikke en ny automat for hver handletur. Du bruker den samme automaten om igjen, med nye flasker hver gang.
En funksjon er akkurat det, i kode: en bit arbeid du gir et navn, slik at du kan be om den igjen og igjen med nye verdier. Alt du skriver på eksamen, er funksjoner — kravbeskrivelsen sier hva de skal hete, hva de skal få inn, og hva de skal gi tilbake.
Nøkkelordet def innfører en ny funksjon. Etter def står navnet, så parameterne i parentes, så et kolon. Alt som hører til funksjonen, står rykket inn fire mellomrom under. Den første linja uten innrykk er utenfor funksjonen igjen.
Å definere en funksjon utfører den ikke. Definisjonen sier bare hva som skal skje hvis noen kaller den senere.
def pant(flasker):
return flasker * 2
print(pant(6))Utskrift:
12Et kall er navnet etterfulgt av parentes med verdiene funksjonen skal jobbe på: pant(6). Parentesen er obligatorisk. Skriver du bare pant, refererer du til funksjonen selv og ikke til resultatet av å kjøre den.
Kallet er et uttrykk: det har en verdi, og den verdien kan du lagre i en variabel, regne videre med eller sende rett inn i print.
def pant(flasker):
return flasker * 2
kvittering = pant(6)
print(kvittering)
print(type(pant))Utskrift:
12
<class 'function'>Den siste linja viser forskjellen: pant uten parentes er selve funksjonen, pant(6) er tallet den gir tilbake.
Et bibliotek skriver ut en hilsen til hver låner som henter en reservert bok. Skriv funksjonen én gang, bruk den to ganger.
Poenget med en funksjon er at definisjonen står ett sted, mens kallene kan stå hvor som helst og hvor mange ganger som helst.
def hils(navn):
print('Hei,', navn, '- boka di ligger klar i skranken.')
hils('Amina')
hils('Jonas')Utskrift:
Hei, Amina - boka di ligger klar i skranken.
Hei, Jonas - boka di ligger klar i skranken.Legg merke til at print(a, b, c) skiller argumentene med ett mellomrom — det er derfor det ikke står noe mellomrom foran bindestreken i koden, men likevel i utskriften.
Funksjonen har ingen return. Den gjør noe (skriver ut) i stedet for å gi tilbake noe. Forskjellen er tema for Løkke 3, og den er en av de sikreste fellene på eksamen.
(Innstegsoppgave — minimal sporing. Sjanger B — kodesporing, altså «hva skriver programmet ut?».) Hva skriver programmet ut?
def dobbel(x):
return x * 2
print(dobbel(3))
print(dobbel(dobbel(3)))Løkke 2 — Parametere og argumenter (~7 min)
En panteautomat som bare kan telle nøyaktig seks flasker, er ubrukelig. Det som gjør en funksjon verdt å skrive, er at den tar imot verdier utenfra og gjør det samme arbeidet på hvilke som helst av dem.
De verdiene har to navn, og eksamensoppgavene bruker begge. Det lønner seg å holde dem fra hverandre.
def-linja: den lokale variabelen funksjonen bruker på verdien den får. Argumentet er den faktiske verdien du sender inn i kallet.I def pant(flasker): er flasker en parameter. I kallet pant(6) er 6 argumentet. Ordene forveksles ofte, men på eksamen står de i oppgaveteksten: «funksjonen skal ta én parameter» betyr at def-linja skal ha nøyaktig ett navn i parentesen.
En funksjon kan ha flere parametere, skilt med komma, og den kan ha null: def meny(): er en helt lovlig definisjon.
Sender du argumentene rett fram, kobles de til parameterne etter rekkefølge: første argument til første parameter, andre til andre. Rekkefølgen er alt — Python kan ikke vite hva du mente.
def differanse(a, b):
return a - b
print(differanse(10, 3))
print(differanse(3, 10))Utskrift:
7
-7Samme funksjon, samme to tall, to helt forskjellige svar. Bytter du om argumentene i en oppgave om for eksempel prisendring, får du fortegnsfeil i hele resten av besvarelsen.
Du kan også navngi argumentene i kallet: differanse(b=3, a=10). Da spiller rekkefølgen ingen rolle, fordi hvert argument sier selv hvilken parameter det hører til.
Navngitte argumenter må stå etter eventuelle posisjonsargumenter i kallet. Bokas kode bruker dem mest når en funksjon har mange parametere og kallet ellers blir uleselig.
def differanse(a, b):
return a - b
print(differanse(b=3, a=10))
print(differanse(10, b=3))Utskrift:
7
7En parameter kan få en standardverdi i def-linja. Da er argumentet valgfritt i kallet: utelater du det, brukes standardverdien; oppgir du det, overstyres den.
Parametere med standardverdi må stå sist i parameterlista. def f(prosent=10, pris) er en syntaksfeil.
def rabattpris(pris, prosent=10):
return pris - pris * prosent / 100
print(rabattpris(200))
print(rabattpris(200, 25))Utskrift:
180.0
150.0Merk at svarene er 180.0 og 150.0, ikke 180 og 150: / gir alltid et flyttall, også når regnestykket går opp.
En rutetabell oppgir planlagt reisetid i minutter. Skriv reisetid(planlagt, forsinkelse=0) som gir den faktiske reisetiden, og vis tre kall: uten forsinkelse, med forsinkelse, og med navngitt argument.
def reisetid(planlagt, forsinkelse=0):
return planlagt + forsinkelse
print(reisetid(24))
print(reisetid(24, 7))
print(reisetid(forsinkelse=7, planlagt=24))Utskrift:
24
31
31De to siste kallene gir samme svar, men er skrevet ulikt. Begge former er like riktige på eksamen.
Standardverdien 0 er valgt fordi den er det nøytrale tilfellet: ingen forsinkelse skal ikke endre reisetiden. Det er den vanligste grunnen til å sette en standardverdi i det hele tatt — den skal svare til «det normale».
En kantine selger boller. Hva skriver programmet ut?
def pris(antall, stykkpris=15):
return antall * stykkpris
print(pris(4))
print(pris(4, 20))
print(pris(stykkpris=20, antall=4))Løkke 3 — return mot print (~9 min)
Nå kommer skillet som avgjør flest poeng i hele Del 2. En funksjon kan vise noe på skjermen, og den kan gi tilbake en verdi til den som kalte den. Det er to helt forskjellige ting, og en oppgave som ber om det ene, gir null uttelling for det andre.
Tenk på panteautomaten igjen: den kan lyse opp beløpet i displayet (det er print), eller den kan skrive ut en kvittering du tar med til kassa og bruker videre (det er return). Bare kvitteringen kan brukes til noe etterpå.
return avslutter funksjonen og sender verdien tilbake til stedet der funksjonen ble kalt. Der erstattes hele kallet av den verdien.Verdien kan være av hvilken som helst type: et tall, en streng, en boolsk verdi, en liste. Er det en liste eller et tall du har regnet ut i en løkke, er det den ferdige verdien etter løkka du returnerer.
def sum_av(verdier):
total = 0
for v in verdier:
total = total + v
return total
resultat = sum_av([12, 7, 31])
print(resultat + 100)Utskrift:
150Fordi sum_av([12, 7, 31]) er tallet 50, kan du regne videre med kallet på samme måte som med et hvilket som helst annet tall.
None er en egen verdi i Python, og den betyr «her er det ingenting». Den skrives med stor forbokstav og er verken 0, tom streng eller False — men den er usann i en if-test.None dukker opp av seg selv i to situasjoner du må kjenne igjen: når en funksjon mangler return, og når et søk ikke fant noe (return None er bokas standardsvar på «ikke funnet»).
verdi = None
print(verdi)
print(verdi is None)Utskrift:
None
TrueBruk is None og ikke == None når du tester. Begge virker, men is None er formen fasitene bruker.
Faller kjøringen ut nederst i funksjonen uten å møte et return, returnerer funksjonen None automatisk. Det gjelder også funksjoner som bare skriver ut noe.
Dette er den vanligste enkeltfeilen i besvarelser: oppgaven ber om en funksjon som returnerer et resultat, kandidaten skriver print i stedet, og alt som skal bruke resultatet videre, får None.
def vis_sum(a, b):
print(a + b)
svar = vis_sum(3, 4)
print(svar)Utskrift:
7
NoneDen første linja i utskriften kommer fra print inne i funksjonen. Den andre viser hva funksjonen faktisk ga tilbake: None.
Så snart return kjøres, hopper Python ut av funksjonen. Kode som står etter, kjøres aldri — heller ikke resten av en løkke return står inne i.
Det er en egenskap du bruker med vilje: står return inne i en if inne i en løkke, stopper funksjonen i det øyeblikket den har funnet svaret sitt.
def finn_forste_negative(verdier):
for v in verdier:
if v < 0:
return v
return None
print(finn_forste_negative([4, 9, -2, -7]))
print(finn_forste_negative([4, 9]))Utskrift:
-2
NoneDet siste return None står utenfor løkka og nås bare hvis løkka gikk helt gjennom uten å finne noe. Nettopp den linja er «ikke funnet»-tilfellet sensor ser etter.
print skriver tegn på skjermen og gir ingen verdi tilbake. return gir en verdi tilbake og skriver ingenting.Regelen i bokas kode, og i fasitene: funksjoner som regner ut noe, returnerer; utskriften skjer der resultatet brukes. Da kan den samme funksjonen gjenbrukes i en senere deloppgave som skal regne videre — og gjenbruk er noe sensor belønner.
Ber oppgaveteksten uttrykkelig om at funksjonen skal skrive ut noe, gjør du selvsagt det. Nøkkelordene i teksten er «returnerer» mot «skriver ut».
En treningslogg har lengden på hver joggetur i kilometer. Vis forskjellen mellom en funksjon som skriver ut totalen, og en som returnerer den — og hva som skjer når du prøver å regne videre.
Først varianten som skriver ut:
def vis_total(turer):
total = 0
for km in turer:
total = total + km
print('Til sammen', total, 'km')
vis_total([5.5, 3.0, 8.2])Utskrift:
Til sammen 16.7 kmDen ser riktig ut, og for øyet er den det. Men prøver du å bruke resultatet, kollapser det:
def vis_total(turer):
total = 0
for km in turer:
total = total + km
print('Til sammen', total, 'km')
svar = vis_total([5.5, 3.0, 8.2])
print(svar)Utskrift:
Til sammen 16.7 km
NoneMed return i stedet er funksjonen brukbar videre:
def total_km(turer):
total = 0
for km in turer:
total = total + km
return total
sum_km = total_km([5.5, 3.0, 8.2])
print('Til sammen', sum_km, 'km')
print('Snitt:', sum_km / 3, 'km')Utskrift:
Til sammen 16.7 km
Snitt: 5.566666666666666 kmLegg merke til 16.7 og ikke 16.700000000000003: her går addisjonen opp. Flyttall gjør ikke alltid det, og skal utskriften være pen, formaterer du den — det kommer i kap. 3.4.
Sensorblikk: de to funksjonene er like lange og like «riktige» som kode. Den andre gir full uttelling på en oppgave som sier «returnerer», den første gir det ikke.
Les kravsetningen i oppgaveteksten én gang til før du skriver def-linja:
- står det «returnerer antall dager over grensen», skal funksjonen ende med return antall — ikke med print(antall);
- står det «skriver ut en tabell», skal den skrive ut.
Skriver du print der oppgaven ber om return, virker programmet ditt tilsynelatende. Men neste deloppgave — som nesten alltid bygger på denne — får None inn og faller sammen. Da mister du poeng to steder for én feil.
Testen du kan gjøre på papir: skriv x = funksjonen(...) under koden din, og spør deg selv hva x er. Er svaret None, har oppgaven fått feil svar.
En nettbutikk gir 10 prosent avslag på kjøp over 500 kroner. Hva skriver programmet ut?
def rabatt(pris):
if pris > 500:
return pris * 0.9
print('Ingen rabatt')
a = rabatt(800)
b = rabatt(300)
print(a)
print(b)En resirkuleringsstasjon veier avfall i kilo.
a) Skriv antall_over(vekter, grense) som returnerer hvor mange av tallene i vekter som er strengt større enn grense.
b) Skriv én linje som skriver ut hvor mange av vektene [4.2, 11.0, 7.5, 2.1] som er over 5.
Løkke 4 — Flere returverdier (~8 min)
Ofte hører to svar sammen: den høyeste temperaturen og hvilken time den ble målt, minste og største verdi, antall treff og selve treffet. Å skrive to nesten like funksjoner som går gjennom de samme dataene to ganger, er både mer arbeid og dårligere uttelling.
Python lar deg returnere flere verdier fra ett return, og fasitene i dette faget bruker det fast.
Skriver du flere verdier etter return, skilt med komma, pakkes de sammen til ett tuppel — en fast, uforanderlig gruppe verdier — og det er tuppelet som returneres.
Du trenger ikke kunne tuppel-apparatet ennå (det kommer i kap. 3.6); du trenger bare å vite at det du får tilbake, inneholder verdiene i den rekkefølgen du skrev dem.
def del_og_rest(teller, nevner):
return teller // nevner, teller % nevner
print(del_og_rest(17, 5))Utskrift:
(3, 2)Utskriften viser parentesene og komma mellom verdiene — slik skriver Python et tuppel. Skulle du hatt tallene hver for seg, pakker du dem ut.
Står det like mange navn på venstre side av likhetstegnet som det er verdier på høyre, får hvert navn sin verdi. Det er dette som gjør flere returverdier praktisk.
Antallet må stemme nøyaktig. To navn og tre verdier gir feilmeldingen ValueError: too many values to unpack, som avbryter programmet.
def del_og_rest(teller, nevner):
return teller // nevner, teller % nevner
hele, rest = del_og_rest(17, 5)
print('Hele:', hele)
print('Rest:', rest)Utskrift:
Hele: 3
Rest: 2Rekkefølgen er den samme som i return-linja. Bytter du om navnene på venstre side, bytter du om betydningen — og det er ingen feilmelding som redder deg.
Alle kodeoppgavene i dette faget besvares med den samme malen. Lær den som en bevegelse, så slipper du å finne på strukturen under tidspress:
1. Signaturen fra kravteksten. Navnet står i oppgaven; parameterne er alt funksjonen trenger utenfra. Ingenting annet.
2. Startverdi før løkka. total = 0, antall = 0, beste = None — det du skal bygge opp.
3. Løkka som går gjennom dataene én gang, og oppdaterer startverdien.
4. return etter løkka, med den ferdige verdien. Skal funksjonen kunne svare «fant ingenting», returnerer den None (eller -1 for en indeks).
def <navn fra oppgaven>(<det den trenger>):
<startverdi>
for <element> in <data>:
<oppdater startverdien>
return <resultatet>Blokken over er en mal, ikke kjørbar kode — den viser formen, ikke et program.
Skal funksjonen svare på to ting, blir siste linje return a, b. Skal den stoppe så snart den har funnet svaret, flyttes return inn i løkka, med et return None etter løkka for «ikke funnet».
Værstasjonen på taket har målt lufttemperaturen hver time gjennom et døgn. Skriv min_og_maks(verdier) som returnerer både den laveste og den høyeste målingen, og vis hvordan du pakker ut begge i kallet.
Malen fra teoremet, med to startverdier i stedet for én. Begge settes til det første elementet, ikke til 0 — 0 ville vært galt for temperaturer under null.
def min_og_maks(verdier):
minste = verdier[0]
storste = verdier[0]
for v in verdier:
if v < minste:
minste = v
if v > storste:
storste = v
return minste, storste
lav, hoy = min_og_maks([-3.5, 1.0, -7.2, 4.8, 0.0])
print('Laveste:', lav)
print('Høyeste:', hoy)
print('Spenn:', hoy - lav)Utskrift:
Laveste: -7.2
Høyeste: 4.8
Spenn: 12.0Tre ting sensor ser etter, og som er verdt å ha i fingrene:
- Startverdiene er verdier[0]. Setter du minste = 0, får du 0 som svar for et døgn der alle målinger er positive, og feil svar for et døgn med bare kuldegrader.
- Én gjennomgang, to svar. Løkka går gjennom lista én gang. To separate funksjoner ville gått gjennom den to ganger — det er ikke galt, men det er mer kode.
- Utpakkingen i kallet viser at du vet hva funksjonen gir tilbake.
Om du heller vil skrive to if/elif eller bruke snarveiene min og max (som kommer i kap. 3.1): begge gir full pott. Fasiten her er bare én av måtene.
Hva skriver programmet ut?
def tell_og_summer(tall):
antall = 0
total = 0
for t in tall:
if t % 2 == 0:
antall = antall + 1
total = total + t
return antall, total
a, b = tell_og_summer([3, 8, 5, 12, 7, 2])
print(a, b)
print(tell_og_summer([1, 3]))En turnering har lagret poengsummen til hver spiller i lista poeng, og navnene i lista navn, slik at navn[i] hører til poeng[i].
a) Skriv beste_spiller(navn, poeng) som returnerer både navnet på spilleren med høyest poengsum og selve poengsummen.
b) Hva skal funksjonen returnere hvis listene er tomme? Skriv løsningen slik at den håndterer det.
Løkke 5 — Lokalt og globalt (~7 min)
Et navn som lages inne i en funksjon, finnes bare der. Det er ikke en teknikalitet — det er hele grunnen til at funksjoner er trygge å gjenbruke: du kan bruke total som navn i ti forskjellige funksjoner uten at de ødelegger for hverandre.
Sporingsoppgavene tester dette direkte, med to variabler som heter det samme inne og ute.
En variabel som får verdi inne i en funksjon — enten som parameter eller ved tilordning — er lokal. Den opprettes når funksjonen kalles og forsvinner når den returnerer.
Prøver du å bruke den utenfor, får du NameError, og programmet stopper.
def regn_ut():
svar = 42
print('Inne i funksjonen:', svar)
regn_ut()
print('Etter kallet finnes ikke svar lenger.')Utskrift:
Inne i funksjonen: 42
Etter kallet finnes ikke svar lenger.En variabel som lages på modulnivå — helt til venstre i fila, utenfor alle funksjoner — kan leses inne i en funksjon uten videre.
Bokas kode bruker dette bare til konstanter: verdier som ikke endrer seg, skrevet med store bokstaver (MVA_SATS, MAKS_LAAN). Alt annet sendes inn som parameter, fordi en funksjon som henter data fra det store rommet rundt seg, ikke lenger kan gjenbrukes uten det rommet.
MVA_SATS = 0.25
def med_mva(pris):
return pris * (1 + MVA_SATS)
print(med_mva(400))Utskrift:
500.0Dette er selve fellen. Tilordner du et navn inne i en funksjon, lager Python en ny, lokal variabel — også når det finnes en global variabel med akkurat samme navn. Den globale er urørt etterpå.
antall = 10
def endre():
antall = 99
print('Inne:', antall)
endre()
print('Ute:', antall)Utskrift:
Inne: 99
Ute: 10Vil du at den nye verdien skal ut av funksjonen, returnerer du den og tilordner utenfor: antall = endre(). Det er formen fasitene bruker; nøkkelordet global er teknisk mulig, men gir uoversiktlig kode og brukes ikke i denne boka.
Et program holder styr på et lagerbeholdning. Hva skjer med den globale variabelen når funksjonen «endrer» den, og hvordan får du endringen ut?
Først den varianten som ikke virker:
beholdning = 50
def selg(antall):
beholdning = beholdning - antall
return beholdning
print('Prøver å selge 10 ...')Utskrift:
Prøver å selge 10 ...Denne blokken skriver bare ledeteksten, for kallet er ikke gjort ennå. Kaller du selg(10), stopper programmet med UnboundLocalError: local variable 'beholdning' referenced before assignment: fordi beholdning tilordnes inne i funksjonen, regnes navnet som lokalt i hele funksjonen — også på høyre side av likhetstegnet, der det ennå ikke har noen verdi.
Slik løser fasiten det — send inn, regn ut, returnér:
def selg(beholdning, antall):
return beholdning - antall
beholdning = 50
beholdning = selg(beholdning, 10)
print(beholdning)
beholdning = selg(beholdning, 15)
print(beholdning)Utskrift:
40
25Funksjonen vet nå ingenting om resten av programmet: den får to tall og gir ett tilbake. Det er nettopp det som gjør at du kan kalle den igjen og igjen — og at neste deloppgave kan gjenbruke den.
Hva skriver programmet ut?
verdi = 5
def dobbelt(verdi):
verdi = verdi * 2
return verdi
print(dobbelt(verdi))
print(verdi)
print(dobbelt(dobbelt(verdi)))
print(verdi)Løkke 6 — Én funksjon, én oppgave (~7 min)
Det siste håndverkskravet er også det som er lettest å overse under tidspress: hver funksjon skal gjøre én ting, og navnet skal si hvilken.
Grunnen er praktisk, ikke estetisk. Eksamensoppgavene er kjeder der deloppgave d) skal bruke funksjonen fra b). Er b) en diger funksjon som både leser, regner og skriver ut, kan du ikke gjenbruke den — og gjenbruk er noe sensor uttrykkelig belønner.
Før du skriver kroppen, skal du kunne si hva funksjonen gjør i én setning som begynner med et verb: «Returnerer antall målinger over grensen.» Klarer du ikke det, gjør funksjonen mer enn én ting, og bør deles.
Det er ikke bare god skikk — det er en egen eksamenssjanger. Sjanger C («forklar med én setning hva funksjonen gjør») går igjen i 60 % (6 av 10 sett), og svaret skal si hva funksjonen oppnår, ikke hvordan koden virker linje for linje.
God: «Returnerer den høyeste verdien i lista og indeksen dens.»
Dårlig: «Den lager først en variabel som heter beste, så går den gjennom lista med en for-løkke, og hvis tallet er større enn beste, så ...»
En funksjon som svarer ja eller nei, returnerer den boolske verdien direkte. Sammenligningen er allerede True eller False — den trenger ingen if rundt seg.
def er_myndig(alder):
return alder >= 18
print(er_myndig(20))
print(er_myndig(17))
print(er_myndig(18))Utskrift:
True
False
TrueFormen if alder >= 18: return True else: return False gir det samme svaret og full uttelling, men er fire linjer der én holder — og konsishet vurderes.
Navnet på en slik funksjon bør leses som et spørsmål: er_myndig, er_ledig, har_plass.
Bokas navn skrives med små bokstaver og understrek mellom ordene: finn_beste, antall_per_type, les_gyldig_alder. Navnet er et verb eller et spørsmål, aldri bare et substantiv.
Norske og engelske navn er like gyldige på eksamen; fasitene i arkivet blander (les_inn_data og item_winner i samme sett). Boka bruker overveiende norske navn.
Ett navn du aldri skal bruke, verken på en funksjon eller en variabel, er navnet på noe innebygd: sum, list, max, input, str, type. Skriver du sum = 0, virker ikke sum(...) i resten av programmet (felle #14 — å skygge et innebygd navn). Bruk total, verdier, tekst i stedet.
Sensor gjentar det samme hvert år: svar kort og klart — er svaret uklart eller lengre enn nødvendig, trekker det ned.
Det rammer særlig sjanger C, der oppgaven ber om én setning om hva en funksjon gjør. Sammenlign:
- Kort og riktig (full uttelling): «Returnerer summen av de positive tallene i lista.»
- Lang og svakere (trekk): «Funksjonen lager først en variabel total som settes til null, deretter går den gjennom hele lista med en for-løkke, og for hvert tall sjekker den om tallet er større enn null, og hvis det er det, legger den tallet til total, og til slutt returnerer den total.»
Den lange varianten er ikke feil. Den forteller bare hvordan koden virker, når spørsmålet var hva den oppnår — og den bruker to minutter du trengte på programmeringsoppgaven. Feilen har nummer #13 i bokas feilregister: ordrik, upresis forklaring.
Her er en funksjon fra et bibliotekssystem. Forklar med én setning hva den gjør — slik sjanger C krever.
def finn_indeks(verdier, mal):
for i in range(len(verdier)):
if verdier[i] == mal:
return i
return -1Blokken over definerer bare funksjonen og skriver ingenting ut.
Svar (én setning): «Returnerer indeksen til det første elementet i lista som er lik mal, eller -1 hvis verdien ikke finnes.»
Setningen er god fordi den sier hva funksjonen oppnår, tar med begge utfallene (funnet og ikke funnet), og er ferdig på én linje. Den nevner ikke løkka, fordi løkka er hvordan, ikke hva.
En vanlig, svakere besvarelse: «Den går gjennom lista med en for-løkke og sammenligner hvert element med mal, og hvis de er like, returnerer den i.» Alt er sant, men spørsmålet var hva funksjonen gjør — og svaret er dobbelt så langt.
Legg også merke til -1 som «ikke funnet». Det er bokas standardsvar når funksjonen skal returnere en indeks; skal den returnere en verdi eller en rad, er standardsvaret None.
Forklar hver av de to funksjonene med én setning som begynner med et verb.
def a_funksjon(verdier, grense):
resultat = 0
for v in verdier:
if v > grense:
resultat = resultat + v
return resultatdef b_funksjon(tekst, tegn):
antall = 0
for t in tekst:
if t == tegn:
antall = antall + 1
return antalla) Forklar den første funksjonen.
b) Forklar den andre funksjonen.
En kommune fører logg over hvor mange millimeter regn som falt hvert døgn i en måned.
a) Skriv er_regnvaersdag(mm) som returnerer True hvis det falt mer enn 0,2 millimeter, og False ellers. Bruk én linje i kroppen.
b) Skriv nedbor_snitt(maalinger) som returnerer gjennomsnittet av tallene i lista. Er lista tom, skal funksjonen returnere None i stedet for å krasje.
En værstasjon har målt lufttemperaturen hver time gjennom ett døgn. Målingene ligger i lista temperaturer med 24 tall, der temperaturer[0] er målingen klokka 00, temperaturer[1] klokka 01 og så videre.
a) Skriv varmeste_time(temperaturer) som returnerer både den høyeste temperaturen og timen den ble målt.
b) Skriv antall_over(temperaturer, grense=20) som returnerer hvor mange målinger som er strengt over grensen. Grensen skal være 20 hvis den som kaller funksjonen ikke oppgir noen.
c) Skriv de to linjene som skriver ut den varmeste timen og antall timer over 25 grader, når målingene ligger i variabelen doegn.
Fem feller som koster poeng hvert år. Feilnumrene er bokas felles register, som du finner samlet i kap. 0.1:
1. print der oppgaven ba om return. Funksjonen gir None, og neste deloppgave — som skal bruke resultatet — faller sammen. Test med x = funksjonen(...) på papir.
2. return inne i løkka når det skulle stått etter. Funksjonen stopper etter første element. Sjekk innrykket: return skal ha samme innrykk som for, ikke som kroppen.
3. Glemt int() eller float() (felle #1 — glemt konvertering). Alt som kommer fra input() eller fra en fil, er tekst. '12' > '9' er usant, fordi tekst sammenlignes tegn for tegn.
4. Startverdien satt til 0 der den skulle vært første element. minste = 0 gir feil svar for temperaturer under null eller for en liste med bare store tall.
5. Å skygge et innebygd navn (felle #14). sum = 0 ødelegger sum(...) i resten av programmet. Bruk total.
To feller til, som er lette å unngå når du vet om dem: å blande / og // (felle #9 — / gir alltid flyttall, // runder nedover), og å skrive en ordrik forklaring der én setning kreves (felle #13).
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 Norges teknisk-naturvitenskapelige universitet. Dette er ikke offisielt studiemateriell. Les mer.