Tilbake
4.1

4.1 Filinnlesing: les fil → 2D-tabell eller streng

Lese en tekstfil linje for linje og bygge en 2D-tabell (liste av lister) eller én streng — det kanoniske første leddet i hver programmeringsoppgave.

55 min
8 oppgaver
Filinnlesingles fil → 2D-tabell eller streng
Din fremgang i kapitlet
0 / 8 oppgaver
Forkunnskaper

- kap. 3.2 — 2D-lister: en liste der hvert element selv er en liste, altså en tabell med rader og kolonner. Det er strukturen vi bygger her.
- kap. 3.3 — strenger: .strip(), .split() og indeksering. Det er verktøyene som gjør én tekstlinje om til én rad.
- kap. 3.5 — ordbøker: brukes i løkke 5, der vi leser fila inn i en ordbok i stedet for en tabell.
- kap. 1.1 — konvertering med int() og float().

Vil du se det samme stoffet i en annen innpakning, går det an å lese Filinnlesing linje for linje i IN1000-boka ved siden av. Den bruker en litt annen løkkeform, men jobben er den samme.

Løkke 1 — Å åpne en fil og lese den linje for linje (~10 min)

En værstasjon lagrer døgnmålingene sine i en helt vanlig tekstfil. Den ser slik ut:

Innholdet i maalinger.txt:

Blindern;12.4;61
Kjevik;15.1;54
Værnes;9.8;73

Tre linjer. Hver linje har et stedsnavn, en temperatur og en luftfuktighet, skilt med semikolon. Det er alt en «datafil» er i dette faget: tekst, én rad per linje, med et skilletegn mellom feltene.

En tekstfil leses ovenfra og ned, én linje om gangen. Du kan ikke hoppe fram og tilbake i den, og du kan ikke lese den samme linja to ganger uten å åpne fila på nytt.

Tekstfil, linje og linjeskift

En tekstfil er en sammenhengende tekst der linjene skilles av et usynlig linjeskifttegn, som i Python skrives '\n'. Tegnet er én bokstav på lik linje med a og ; — det ser du bare ikke.

Derfor gjelder to ting som forvirrer alle første gang:

- Hver linje du leser fra en fil ender på '\n' (den aller siste kan mangle det).
- print legger på sitt eget linjeskift i tillegg. Skriver du ut en ulest-renset linje, får du en blank linje under.

Løsningen på begge er .strip(), som du møter i løkke 2.

`open(filnavn, 'r')`

Åpner en tekstfil for lesing og gir deg et filobjekt — en peker som husker hvor langt du har lest.

'r' står for read. Det er standardverdien, så open('maalinger.txt') betyr det samme, men boka skriver modusen ut fordi du snart skal skrive 'w', 'a', 'wb' og 'rb' i samme posisjon.

f = open('maalinger.txt', 'r')
forste = f.readline()
print(forste)
f.close()

Utskrift:

Blindern;12.4;61

Legg merke til den blanke linja i utskriften: linja fra fila har med seg sitt eget '\n', og print legger på ett til.

Filnavnet er en helt vanlig streng, så du kan bygge det: navn + '.txt'. Finnes ikke fila, stopper programmet med en feil som heter FileNotFoundError — den håndterer vi i kap. 4.3.

`f.close()`

Lukker fila og frigjør den. Når du leser, er trekket for en glemt close() lite; når du skriver, kan det koste selve dataene (kap. 4.2).

Regelen i denne boka: hver open har en close, og close står etter løkka — ikke inne i den. Lukker du fila inne i løkka, krasjer neste runde.

`for linje in f:`

Går gjennom fila én linje av gangen, uten at du trenger en teller eller en stoppbetingelse. Løkka avslutter av seg selv når fila er slutt.

Variabelen linje er en streng med hele linja, inkludert linjeskiftet på slutten.

f = open('maalinger.txt', 'r')
for linje in f:
    print(linje.strip())
f.close()

Utskrift:

Blindern;12.4;61
Kjevik;15.1;54
Værnes;9.8;73

Dette er formen boka bruker overalt. Den er kortere og tryggere enn while-varianten med readline(), fordi du ikke kan glemme å lese neste linje.

Navnekollisjon å være klar over: f er filobjektet her. f brukes også som prefikset i en f-streng (f'{x:.2f}', se kap. 3.4). De to har ingenting med hverandre å gjøre, og du ser forskjellen på at f-strengen har en fnutt rett etter f.

✏️Eksempel 1: Les fila og tell linjene

Skriv et program som leser maalinger.txt, skriver ut hver linje med linjenummer foran, og til slutt sier hvor mange linjer fila hadde.

Innholdet i maalinger.txt:
Blindern;12.4;61
Kjevik;15.1;54
Værnes;9.8;73

Selve løkka er hele oppskriften; telleren er en vanlig teller fra kap. 1.3.

f = open('maalinger.txt', 'r')
antall = 0
for linje in f:
    antall = antall + 1
    print(antall, linje.strip())
f.close()
print('Antall linjer:', antall)

Utskrift:

1 Blindern;12.4;61
2 Kjevik;15.1;54
3 Værnes;9.8;73
Antall linjer: 3

Slik ville sensor sett på det: fire ting gir uttelling hver for seg — open før løkka, for linje in f:, det du gjør med linja, og close etter løkka. Glemmer du close(), er trekket lite. Setter du close() inne i løkka, stopper programmet på andre runde, og det koster mer.

Dette er også én av flere korrekte løsninger: du kunne telt med len(f.readlines()) i stedet. Begge gir full pott — sensor er ute etter riktig struktur, ikke én bestemt formulering.

📝Oppgave 1

(Innstegsoppgave — sjanger B, kodesporing: «hva skriver dette programmet ut?».) Hva skriver dette programmet ut? Skriv utskriften nøyaktig, med linjeskift slik terminalen viser den.

linje = 'Kjevik;15.1;54\n'
print(linje)
print(linje.strip())
print('ferdig')

Løkke 2 — Rens først, del så (~12 min)

En linje fra fila er sjelden interessant som én tekst. Du vil ha tak i feltene: stedet, temperaturen, fuktigheten.

Å parse en linje betyr nettopp det: å tolke en tekstlinje og hente ut feltene den består av. Det gjøres i to steg, og rekkefølgen er fast: rens først med .strip(), del så med .split().

Parsing (å tolke en linje og hente ut feltene)
Parsing er å gjøre om en tekstlinje til de enkeltverdiene den representerer.

Linja 'Kjevik;15.1;54' er for datamaskinen bare 14 tegn. At det er et sted, en temperatur og en luftfuktighet, er noe du vet — og parsingen er der du forteller programmet det.

I dette faget er parsingen alltid den samme lenken: linje.strip().split(separator), etterfulgt av int() eller float() på tallfeltene.

Separator (skilletegn)
Separatoren er tegnet som skiller feltene i en linje. Den er en del av dataformatet, ikke noe du kan velge.

De tre du møter på eksamen er semikolon (';'), komma (',') og tabulator ('\t', ett tabulatortegn). Mellomrom er den fjerde, og den har en egen form: .split() uten argument.

Skriv aldri separatoren på slump. Se på fila først — det tar to sekunder og redder hele oppgaven.

`.strip()`

Gir en ny streng uten blanktegn i begge ender — mellomrom, tabulator og linjeskift.

raa = 'Kjevik;15.1;54\n'
print(len(raa))
ren = raa.strip()
print(len(ren))
print(ren)

Utskrift:

15
14
Kjevik;15.1;54

Lengden går fra 15 til 14: linjeskiftet er ett tegn, og det var det eneste som forsvant. Semikolonene inni linja blir aldri rørt, fordi .strip() bare tar fra endene.

Originalen raa er uendret — strenger kan ikke endres, du får alltid en ny.

`.strip(tegn)`

Med et argument fjerner .strip() de tegnene du oppgir, fra begge ender, i stedet for blanktegn:

print('***Blindern***'.strip('*'))
print('  Kjevik  '.strip())
print('..12.4..'.strip('.'))

Utskrift:

Blindern
Kjevik
12.4

Merk at argumentet er en mengde tegn, ikke en tekst som må stå samlet: .strip('.*') fjerner både punktum og stjerner. Varianten uten argument er den du bruker i 99 % av filoppgavene.

`.split(separator)`

Deler en streng i en liste av felt, med separatoren som skille. Separatoren selv blir borte.

felt = 'Kjevik;15.1;54'.split(';')
print(felt)
print(len(felt))
print(felt[0], felt[2])

Utskrift:

['Kjevik', '15.1', '54']
3
Kjevik 54

Antall felt er alltid antall separatorer pluss én. Har en linje tre felt og du ber om felt[3], stopper programmet med IndexError.

Er separatoren fraværende i strengen, får du en liste med ett element — hele strengen. Det er det du ser når du har brukt feil skilletegn.

`.split()` uten argument

Uten argument deler .split()vilkårlig mange blanktegn — ett mellomrom eller ti, og tabulator også. Tomme felt oppstår ikke.

print('Blindern   12.4      61'.split())
print('Blindern 12.4 61'.split(' '))
print('Blindern   12.4      61'.split(' '))

Utskrift:

['Blindern', '12.4', '61']
['Blindern', '12.4', '61']
['Blindern', '', '', '12.4', '', '', '', '', '', '61']

Se på den siste: med ' ' som eksplisitt separator blir hvert ekstra mellomrom til et tomt felt. Derfor er .split() uten argument den riktige når fila er kolonnejustert med varierende mellomrom.

`linje.strip().split(sep)`

Bokas parselenke, lest fra venstre: .strip() gir en ny streng uten linjeskiftet, og .split(sep) deler den i felt.

linje = 'Værnes;9.8;73\n'
felt = linje.strip().split(';')
print(felt)
print(felt[-1] == '73')

Utskrift:

['Værnes', '9.8', '73']
True

Rekkefølgen er fast. Gjør du det motsatt — linje.split(';') og så .strip() på hele lista — får du ikke engang lov: en liste har ingen .strip().

📜Kodemønster: les fil → 2D-tabell

Bokas viktigste mønster. Det skal sitte så godt at du kan skrive det på papir uten å tenke, for det er deloppgave a i hver eneste programmeringsoppgave.

def les_tabell(filnavn):
    tabell = []
    f = open(filnavn, 'r')
    for linje in f:
        tabell.append(linje.strip().split(separator))
    f.close()
    return tabell

Blokken er en mal med en plassholder (separator) og er derfor merket som ikke-kjørbar.

Seks faste deler, og hver av dem gir uttelling for seg:

1. Tom liste før løkka — den blir tabellen.
2. open før løkka.
3. for linje in f:.
4. .strip().split(...) i den rekkefølgen, med riktig separator.
5. append av raden — én rad per linje.
6. close etter løkka, og return tabell til slutt.

Glemmer du return, får kalleren None, og resten av programmet ditt krasjer på noe som ser ut som en helt annen feil.

✏️Eksempel 2: Fra fil til 2D-tabell

Skriv les_tabell(filnavn) som leser maalinger.txt og returnerer en 2D-liste med én rad per linje og ett felt per kolonne. Skriv ut tabellen, antall rader, antall kolonner og feltet i rad 1, kolonne 0.

Innholdet i maalinger.txt:
Blindern;12.4;61
Kjevik;15.1;54
Værnes;9.8;73

def les_tabell(filnavn):
    tabell = []
    f = open(filnavn, 'r')
    for linje in f:
        tabell.append(linje.strip().split(';'))
    f.close()
    return tabell

tabell = les_tabell('maalinger.txt')
print(tabell)
print(len(tabell), len(tabell[0]))
print(tabell[1][0])

Utskrift:

[['Blindern', '12.4', '61'], ['Kjevik', '15.1', '54'], ['Værnes', '9.8', '73']]
3 3
Kjevik

Les utskriften nøye. Ytterlista har tre elementer — én per linje. Hvert element er selv en liste med tre strenger. len(tabell) er antall rader, len(tabell[0]) er antall kolonner i første rad.

Alle feltene er strenger, også '15.1' og '54'. Det er neste løkkes tema, og det er feilkode #1 i praksis.

Slik ville sensor sett på det: dette er mønsterets seks deler, satt rett inn. Har du strukturen riktig, men skriver .split(',') fordi du leste fila for fort, får du fortsatt god uttelling på deloppgaven — riktig overordnet struktur belønnes selv med en slik feil. Men de påfølgende deloppgavene blir vanskeligere, for du drar feilen med deg.

📝Oppgave 2
Sjanger E

Fila glass.txt har én linje per by med formen by;antall:

Innholdet i glass.txt:

Bergen;120
Tromsø;45
Stavanger;88

a) Skriv les_linjer(filnavn) som returnerer en liste med rensede linjer, altså ['Bergen;120', 'Tromsø;45', 'Stavanger;88'].

b) Hva må du endre i funksjonen for å få en 2D-tabell i stedet?

📝Oppgave 3
Eksamensnivå, sjanger B

Fila glass.txt inneholder:

Bergen;120
Tromsø;45
Stavanger;88

Hva skriver programmet ut?

f = open('glass.txt', 'r')
byer = []
for linje in f:
    felt = linje.split(';')
    byer.append(felt[0])
f.close()
print(byer)
print(len(byer))

Løkke 3 — Konverter tallene (~10 min)

Alt som kommer fra en fil er tekst. Også '54'. Også '15.1'. Filer inneholder ikke tall — de inneholder tegn som ser ut som tall.

Skal du regne, sammenligne eller sortere, må feltet gjennom int() eller float() først. Dette er feilkode #1, og det er den hyppigste feilen i hele faget.

— naturlig pausepunkt: har du lest hit, har du hele deloppgave a. Resten av kapitlet er varianter. —

`int(s)` og `float(s)` etter innlesing
int(s) gjør en streng om til et heltall, float(s) til et desimaltall. Begge stopper programmet med ValueError hvis strengen ikke ser ut som et tall.

felt = ['Kjevik', '15.1', '54']
print(felt[2] + felt[2])
print(int(felt[2]) + int(felt[2]))
print(float(felt[1]) * 2)

Utskrift:

5454
108
30.2

Første linje er feilen i ren form: + på to strenger skjøter dem sammen. Programmet krasjer ikke — det svarer 5454.

Tommelfingerregel: konverter i samme linje som du henter feltet, mens du husker hva kolonnen betyr. Bruk float for alt som kan ha desimaler (pris, temperatur, tid) og int for antall.

✏️Eksempel 3: Konverter under innlesingen

Utvid les_tabell slik at temperaturen blir et flyttall og fuktigheten et heltall, mens stedsnavnet forblir tekst. Regn deretter ut gjennomsnittstemperaturen.

Innholdet i maalinger.txt:
Blindern;12.4;61
Kjevik;15.1;54
Værnes;9.8;73

def les_maalinger(filnavn):
    tabell = []
    f = open(filnavn, 'r')
    for linje in f:
        felt = linje.strip().split(';')
        tabell.append([felt[0], float(felt[1]), int(felt[2])])
    f.close()
    return tabell

data = les_maalinger('maalinger.txt')
print(data)
sum_temp = 0
for rad in data:
    sum_temp = sum_temp + rad[1]
print('Snitt:', sum_temp / len(data))

Utskrift:

[['Blindern', 12.4, 61], ['Kjevik', 15.1, 54], ['Værnes', 9.8, 73]]
Snitt: 12.433333333333332

Nå står tallene uten anførselstegn i utskriften. Det er den enkleste måten å se at konverteringen faktisk skjedde.

Snittet har mange desimaler. Det er slik flyttall er — 37,3/337{,}3 / 3 kan ikke skrives eksakt binært, og Python viser deg hele svaret. Vil du ha to desimaler i en rapport, formaterer du ved utskrift, ikke ved lagring: '{:.2f}'.format(sum_temp / len(data)) eller f'{sum_temp / len(data):.2f}' (se kap. 3.4). Begge former er gyldige; f-strengen er den nyere.

Slik ville sensor sett på det: her ligger poengene på at hvert felt får riktig type, og på at stedsnavnet ikke konverteres. En løsning som konverterer i en egen løkke etterpå, gir like full pott — det finnes flere riktige veier.

📝Oppgave 4
Eksamensnivå, sjanger E

Fila stromspris.txt har én linje per prisområde, og feltene er skilt med ett tabulatortegn:

Innholdet i stromspris.txt:

NO1	0.87
NO3	0.42
NO5	0.55

a) Skriv les_priser(filnavn) som returnerer en 2D-liste der prisen er et flyttall.

b) Skriv koden som regner ut den høyeste prisen i tabellen, uten å bruke max.

c) Skriv den samme utregningen med max.

Løkke 4 — Overskriftsrad, og hele fila på én gang (~10 min)

Mange datafiler har en overskriftsrad øverst som navngir kolonnene. Den skal ikke inn i tabellen — den er metadata, ikke data. Prøver du å konvertere den, krasjer programmet på ordet dager.

Til gjengjeld er overskriftsraden en gave: den lar deg finne kolonnen ved navn i stedet for å anta hvilken posisjon den har.

Overskriftsrad (header)

Den første linja i en datafil, som navngir kolonnene i stedet for å inneholde data.

Du kjenner den igjen på at feltene er ord der resten av fila har tall. Behandlingen er alltid den samme: les den for seg, før løkka, og bruk den enten til å hoppe over eller til å slå opp kolonnenavn.

Eksamensoppgaven sier alltid om fila har en slik rad. Står det ingenting, har den det ikke.

`f.readline()`

Leser én linje og flytter posisjonen i fila ett hakk fram. Linja kommer med linjeskiftet på slutten.

Kalt før en for-løkke er dette den vanlige måten å hoppe over overskriftsraden: løkka fortsetter der readline slapp.

f = open('utlaan.txt', 'r')
overskrift = f.readline()
print(overskrift.strip())
antall = 0
for linje in f:
    antall = antall + 1
f.close()
print('Datalinjer:', antall)

Utskrift:

tittel;låner;dager
Datalinjer: 3

Er fila slutt, gir readline() den tomme strengen ''. En blank linje midt i fila gir '\n' — de to er ikke det samme.

`f.readlines()`

Leser hele fila og gir deg en liste med alle linjene, hver med sitt linjeskift.

f = open('maalinger.txt', 'r')
linjer = f.readlines()
f.close()
print(linjer)
print(len(linjer))
print(linjer[0].strip())

Utskrift:

['Blindern;12.4;61\n', 'Kjevik;15.1;54\n', 'Værnes;9.8;73\n']
3
Blindern;12.4;61

Praktisk når du trenger tilfeldig tilgang til linjene (for eksempel den siste), eller vil vite antallet før du begynner. Ulempen er at hele fila havner i minnet på én gang — irrelevant for en eksamensfil på ti linjer.

`f.read()`

Leser hele fila som én streng, med alle linjeskiftene inni.

f = open('maalinger.txt', 'r')
tekst = f.read()
f.close()
print(len(tekst))
print(tekst.count('\n'))
print(tekst.strip().split('\n'))

Utskrift:

46
3
['Blindern;12.4;61', 'Kjevik;15.1;54', 'Værnes;9.8;73']

Dette er «les fil til streng»-varianten. Den brukes når oppgaven handler om teksten som helhet — telle tegn eller ord, snu teksten, lete etter et delord.

tekst.strip().split('\n') gir deg linjene tilbake som en liste, uten linjeskift. Det er ofte den ryddigste veien.

`overskrift.index(navn)`

Finner posisjonen til et kolonnenavn i overskriftsraden, slik at du slipper å anta at «dager» er kolonne 2.

overskrift = ['tittel', 'låner', 'dager']
print(overskrift.index('dager'))
print(overskrift.index('tittel'))

Utskrift:

2
0

Dette er et eksplisitt fullscore-krav på eksamen (feilkode #4 — anta fast kolonnerekkefølge). Skriver du felt[2], virker koden på akkurat den fila og ryker hvis kolonnene bytter plass. Skriver du felt[overskrift.index('dager')], virker den uansett.

Finnes ikke navnet, stopper programmet med ValueError — det er en ærlig feil, og bedre enn et stille galt svar.

✏️Eksempel 4: Overskriftsrad og kolonne funnet ved navn

Fila utlaan.txt har en overskriftsrad. Skriv les_utlaan(filnavn) som returnerer overskriften og en 2D-tabell der dagerkolonnen er heltall — uten å anta hvilken posisjon den kolonnen har.

Innholdet i utlaan.txt:
tittel;låner;dager
Sult;Ida;14
Markens grode;Omar;21
Naiv Super;Lise;7

def les_utlaan(filnavn):
    f = open(filnavn, 'r')
    overskrift = f.readline().strip().split(';')
    k = overskrift.index('dager')
    tabell = []
    for linje in f:
        felt = linje.strip().split(';')
        felt[k] = int(felt[k])
        tabell.append(felt)
    f.close()
    return overskrift, tabell

overskrift, tabell = les_utlaan('utlaan.txt')
print(overskrift)
print(tabell)
print('Kolonnen «dager» ligger på plass', overskrift.index('dager'))

Utskrift:

['tittel', 'låner', 'dager']
[['Sult', 'Ida', 14], ['Markens grode', 'Omar', 21], ['Naiv Super', 'Lise', 7]]
Kolonnen «dager» ligger på plass 2

Tre ting skjer her, og alle tre er poenggivende.

Overskriftsraden leses med readline() før løkka, så for linje in f: starter på første datalinje. Kolonneindeksen k finnes ved navn, én gang, før løkka — ikke inni den. Og funksjonen returnerer to verdier som et tuppel, pakket ut i to variabler av kalleren (kap. 3.6).

Legg merke til variabelnavnet k. I dette kapitlet betyr k en kolonneindeks. I ordbokkapitlene betyr k en nøkkel. Samme bokstav, to helt ulike ting — se etter hva den brukes til.

Slik ville sensor sett på det: readline()-hoppet er ett poeng, det dynamiske kolonneoppslaget er et eksplisitt fullscore-krav, og konverteringen er et tredje. Hardkoder du felt[2] = int(felt[2]), mister du bare fullscore-punktet — resten står.

📝Oppgave 5
Eksamensnivå, sjanger E

Bruk utlaan.txt fra eksempel 4:

Innholdet i utlaan.txt:

tittel;låner;dager
Sult;Ida;14
Markens grode;Omar;21
Naiv Super;Lise;7

a) Hva skjer hvis du glemmer readline()-hoppet og prøver int(felt[2]) på hver linje?

b) Skriv les_kolonne(filnavn, navn) som returnerer verdiene i den kolonnen som heter navn, som en liste med strenger — uten å anta posisjonen.

c) Hva returnerer les_kolonne('utlaan.txt', 'sjanger'), og hvorfor?

Løkke 5 — Les fil til ordbok i stedet (~8 min)

En 2D-tabell er riktig når du skal gå gjennom alle radene. Skal du slå opp en bestemt rad — «hva var temperaturen på Kjevik?» — er en ordbok (kap. 3.5) bedre: da går oppslaget rett på, uten å lete.

Mønsteret er det samme som før helt til append-linja. Der bytter du ut å legge til en rad med å sette inn en nøkkel.

📜Kodemønster: les fil → ordbok
def les_ordbok(filnavn):
    d = {}
    f = open(filnavn, 'r')
    for linje in f:
        felt = linje.strip().split(separator)
        d[felt[0]] = felt[1:]
    f.close()
    return d

Blokken er en mal med en plassholder og er merket som ikke-kjørbar.

Det eneste nye er linja i midten, og den har to valg du må ta bevisst:

1. Hvilken kolonne er nøkkelen? Nesten alltid den første, men les oppgaven. Nøkler er unike — er det to linjer med samme nøkkel, overskriver den siste den første, og du mister en rad uten noen feilmelding.
2. Hva er verdien? Resten av raden (felt[1:]), ett enkelt felt (felt[1]), eller et konvertert tall. Velg det oppgaven faktisk trenger.

✏️Eksempel 5: Fil til oppslagsordbok

Les maalinger.txt inn i en ordbok fra stedsnavn til [temperatur, fuktighet], med tallene konvertert. Slå opp Kjevik.

Innholdet i maalinger.txt:
Blindern;12.4;61
Kjevik;15.1;54
Værnes;9.8;73

def les_ordbok(filnavn):
    d = {}
    f = open(filnavn, 'r')
    for linje in f:
        felt = linje.strip().split(';')
        d[felt[0]] = [float(felt[1]), int(felt[2])]
    f.close()
    return d

maalinger = les_ordbok('maalinger.txt')
print(maalinger)
print(maalinger['Kjevik'])
print(maalinger['Kjevik'][0])
print('Blindern' in maalinger, 'Bergen' in maalinger)

Utskrift:

{'Blindern': [12.4, 61], 'Kjevik': [15.1, 54], 'Værnes': [9.8, 73]}
[15.1, 54]
15.1
True False

Oppslaget maalinger['Kjevik'] går rett på, uten å gå gjennom de andre radene. Det er hele poenget med ordboka.

Slår du opp en nøkkel som ikke finnes, stopper programmet med KeyError. Derfor står in-testen på siste linje: den er den trygge måten å spørre «finnes denne?» på.

Slik ville sensor sett på det: valget mellom tabell og ordbok er sjelden feil i seg selv — det er begrunnelsen som teller. Skal du slå opp, velg ordbok. Skal du gå gjennom alt eller sortere, velg tabell.

📝Oppgave 6
Eksamensnivå, sjanger E

Fila glass.txt har linjer på formen by;antall:

Innholdet i glass.txt:

Bergen;120
Tromsø;45
Stavanger;88

a) Skriv les_glass(filnavn) som returnerer ordboka {by: antall} med antallet som heltall.

b) Skriv koden som finner samlet antall, ved å gå gjennom verdiene i ordboka.

c) Hva skjer med ordboka hvis fila får en fjerde linje Bergen;200?

Løkke 6 — with, og valget mellom de tre formene (~5 min)

Du har nå tre måter å ta imot en fil på, og de dekker alt eksamen spør om:

Du skal …Les fila som …
gå gjennom radene, sortere, finne beste2D-tabell
slå opp en bestemt nøkkelordbok
telle tegn eller ord, snu tekstenén streng med .read()

Til slutt en variant av selve åpningen, som du vil se i andre bøker og i noen løsningsforslag.
`with open(filnavn) as f:`

Åpner fila og lukker den automatisk når blokken er ferdig — også hvis det skjer en feil underveis.

with open('maalinger.txt', 'r') as f:
    tabell = []
    for linje in f:
        tabell.append(linje.strip().split(';'))
print(len(tabell))
print(f.closed)

Utskrift:

3
True

f.closed er sann etterpå: fila er lukket uten at du skrev close().

Bokas hovedform er likevel openclose, fordi det er den formen løsningsforslagene i arkivet bruker, og fordi den gjør de to stegene synlige for sensor. with er fullt gyldig og gir full pott — bruk den formen du husker best under press, men bland dem aldri i samme funksjon.

📝Oppgave 7
Eksamensnivå, sjanger E

Et bibliotek lagrer utlånene sine i utlaan.txt, med en overskriftsrad:

Innholdet i utlaan.txt:

tittel;låner;dager
Sult;Ida;14
Markens grode;Omar;21
Naiv Super;Lise;7

a) Skriv les_utlaan(filnavn) som hopper over overskriftsraden og returnerer en 2D-tabell der dager er et heltall og de øvrige feltene er strenger. Kolonnerekkefølgen skal ikke antas kjent.

b) Skriv lengste_laan(tabell, overskrift) som returnerer tittelen på boka med flest dager, uten å bruke max.

c) Hva returnerer funksjonen i b) hvis tabellen er tom, og hvorfor er det et bevisst valg?

📝Oppgave 8
Eksamensnivå, sjanger B

Fila maalinger.txt inneholder:

Blindern;12.4;61
Kjevik;15.1;54
Værnes;9.8;73

Hva skriver programmet ut?

f = open('maalinger.txt', 'r')
tekst = f.read()
f.close()
linjer = tekst.strip().split('\n')
print(len(linjer))
d = {}
for linje in linjer:
    felt = linje.split(';')
    d[felt[0]] = int(felt[2])
print(d['Værnes'] - d['Kjevik'])
print(sorted(d))

API- og konstruksjonsliste

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.