3.3 Strenger

Strenger som tegnsekvenser: gjennomløping tegn for tegn, `.split()`, `.rstrip()`/`.strip()`, bygging med `+` og `str()` — grunnlaget for streng-funksjonene i Oppgave 3 og for filinnlesing.

45 min
8 oppgaver
Strenger
Din fremgang i kapitlet
0 / 8 oppgaver

Forkunnskaper — sist du var her

Kap. 3.1 — Lister — fordi .split() gir deg en liste
— og kap. 1.1 — Variabler, datatyper og uttrykk, der du møtte tekst som datatype første gang.

De tre tingene du bruker mest her:

- at + på to tekster skjøter dem sammen"1" + "2" gir "12"»), mens
+ på to tall legger dem sammen,
- int(tekst) og str(tall) for å veksle mellom de to,
- bygg-mønsteret: startverdi før løkka, oppdatering inne i den, bruk etter.

Kort oppfrisket:

navn = "Ada" poeng = 12 print(navn + " har " + str(poeng) + " poeng")

Utskrift:

Ada har 12 poeng

I dette kapitlet ser vi på teksten innenfra: den er en rekke tegn du kan gå gjennom, hente ut av og bygge nye tekster av.

Løkke 1 — Teksten som en rekke tegn (~11 min)

En sykkelutleie merker hver sykkel med en kode som "R31-2026": en bokstav for stativet, to sifre for plassen, en bindestrek og et årstall. Skal programmet plukke ut plassnummeret, må det kunne se inne i teksten.

Det kan det. En tekst er en sekvens — akkurat som en liste — og nesten alt du lærte om lister, virker uendret.

Streng som sekvens

En tekst er en rekke enkelttegn i fast rekkefølge. Du kan måle lengden, indeksere og løpe gjennom den, nøyaktig som med en liste:

tekst = "sykkel" print(len(tekst))
print(tekst[0], tekst[3], tekst[-1])
for tegn in "bil":
    print(tegn)

Utskrift:

6 s k l b i l

Tellingen starter på null, og negativ indeks teller bakfra — samme regler som i
kap. 3.1.

Den ene store forskjellen kommer i neste definisjon: en liste kan endres, en tekst kan ikke.

Indeksering `tekst[i]`

Henter ut ett tegn som en tekst av lengde 1:

kode = "A4213" print(kode[0])
print(kode[1] + kode[2])
print(int(kode[1] + kode[2]))

Utskrift:

A
42
42

De to siste linjene er verdt å studere. kode[1] er teksten "4" og kode[2] er teksten "2", så plusstegnet skjøter dem til "42" — det er ikke tallet seks. Først int(...) gjør det om til et tall, og da ser utskriften tilfeldigvis lik ut.

Skulle du regnet med sifrene, måtte hvert av dem konverteres for seg:
int(kode[1]) + int(kode[2]) gir 6. Dette er feilkode #3 i sin reneste form.

`len(tekst)`

Gir antall tegn, medregnet mellomrom og tegnsetting:

navn = "Ada" print(len(navn), len(""), len("to ord"))

Utskrift:

3 0 6

Merk den tomme teksten "" med lengde 0 — den er startpunktet i bygge-mønsteret lenger nede, og den er kanttilfellet du skal sjekke funksjonene dine på.

Og merk at "to ord" har seks tegn, ikke fem. Mellomrommet er et tegn som alle andre.

`for tegn in tekst:`

Går gjennom teksten tegn for tegn. Løkkevariabelen er en tekst av lengde 1:

antall = 0 for tegn in "kollektiv":
    if tegn == "l":
        antall = antall + 1 print(antall)

Utskrift:

2

Dette er den formen du skal bruke når du bare trenger tegnene. Trenger du
plassen — for eksempel for å gå bakfra, eller for å sammenligne med
naboen — bruker du for i in range(len(tekst)): i stedet, og henter tegnet med
tekst[i].

Valget er nøyaktig det samme som for lister, og svaret på det samme spørsmålet:
trenger du plassen?

Strenger er uforanderlige

En tekst kan ikke endres etter at den er laget. Dette går ikke:

tekst = "bil" tekst[0] = "s"

Programmet stopper, og siste linje i feilmeldingen er TypeError: 'str' object does not support item assignment. Blokken er merket som ikke-kjørbar fordi feilen er plantet med vilje.

Løsningen er alltid den samme: bygg en ny tekst i stedet.

tekst = "bil" ny = "s" + tekst[1] + tekst[2]
print(tekst, ny)

Utskrift:

bil sil

Legg merke til at den opprinnelige teksten er urørt. Det er en egenskap, ikke en begrensning: en tekst du har sendt til en funksjon, kan aldri komme endret tilbake, og det gjør tekster trygge å regne med.

✏️Eksempel 1: En sykkelkode, lest fra innsiden

Sykkelutleien merker syklene med koder som "R31-2026". Skriv ut kodens lengde, første og siste tegn, hvor mange sifre den inneholder, og plassnummeret — de to tegnene etter bokstaven — både som tekst og som tall.

Alt hentes ut av den samme teksten:

billett = "R31-2026" print(len(billett))
print(billett[0], billett[-1])
antall_sifre = 0 for tegn in billett:
    if tegn >= "0" and tegn <= "9":
        antall_sifre = antall_sifre + 1 print(antall_sifre)
print(billett[1] + billett[2], int(billett[1] + billett[2]) + 1)

Utskrift:

8
R 6
6
31 32

Tre ting er verdt å merke seg.

Bindestreken teller med i lengden. Åtte tegn, ikke sju — og heller ikke fire.
Alt mellom anførselstegnene er med.

Sifferbetingelsen tegn >= "0" and tegn <= "9" sammenligner tekster, ikke
tall. Det virker fordi tegn sammenlignes etter rekkefølgen i tegnsettet, der sifrene står samlet. Denne betingelsen kommer til å dukke opp i hver eneste oppgave om koder og skjemaer.

Siste linje viser de to plusstegnene ved siden av hverandre.
billett[1] + billett[2] skjøter to tekster til "31", mens int(...) + 1 legger sammen tall og gir 32. Samme tegn, to helt ulike betydninger — avgjort av typen.

📝Oppgave 1

(Innstegsoppgave — ren gjengivelse.) En kantine merker dagens rett med koden

kode = "B12"

a) Hva gir len(kode)?

b) Hva gir kode[0]?

c) Hva gir kode[-1]?

d) Hva gir kode[1] + kode[2]?

e) Hva gir int(kode[1] + kode[2])?

f) Hva skjer hvis du skriver kode[0] = "C"?

📝Oppgave 2
Eksamensnivå, sjanger A

Hva skriver programmet ut? Skriv utskriften nøyaktig, med mellomrom og linjeskift slik terminalen viser den.

tekst = "buss" ny = "" for tegn in tekst:
    ny = tegn + ny print(ny)
print(len(ny), tekst)

Løkke 2 — Å bygge en ny tekst tegn for tegn (~12 min)

Fordi en tekst ikke kan endres, har alle «lag en ny tekst der …»-oppgaver samme løsning: du starter med ingenting og setter sammen underveis. Det er sensors standardmetode i sjanger E, og den er verdt å kunne blindt.

📜Tegn-for-tegn-mønsteret

Bokas åttende kodemønster, og svaret på enhver oppgave som ber om «en ny tekst der …».

Oppskriften har tre faste steg:

1. Før løkka: ny = "" — den tomme teksten.
2. Inne i løkka: ny = ny + tegn for de tegnene som skal være med.
3. Etter løkka: return ny.

tekst = "kollektivtrafikk" ny = "" for tegn in tekst:
    if tegn != "k":
        ny = ny + tegn print(ny)

Utskrift:

olletivtrafi

Det er nøyaktig samme skjelett som bygg-en-ny-liste-mønsteret fra
kap. 3.1 — bare med "" i stedet for [], og plusstegnet i stedet for append.

Rekkefølgen i oppdateringen avgjør retningen. ny = ny + tegn bygger forfra;
ny = tegn + ny bygger bakfra og snur teksten. De to ser nesten like ut, og de gir motsatt svar.

`+` og `+=` på tekster
+ skjøter to tekster til en ny. += er kortformen for «legg til på slutten av det jeg allerede har»:

del1 = "sykkel" del2 = "utleie" print(del1 + " " + del2)
ny = "" ny = ny + "a" ny += "b" print(ny, len(ny))

Utskrift:

sykkel utleie ab 2

Merk at mellomrommet må skrives inn selv, som en egen tekst " ". Plusstegnet setter tekstene helt inntil hverandre.

ny += "b" betyr nøyaktig det samme som ny = ny + "b". Begge er greie på eksamen — velg én og hold deg til den gjennom hele besvarelsen.

`str(tall)`

Gjør et tall om til tekst, slik at det kan skjøtes sammen med andre tekster:

antall = 12 print("Vi har " + str(antall) + " sykler")
print(str(3.5) + "!", len(str(100)))

Utskrift:

Vi har 12 sykler
3.5! 3

Uten str(...) ville første linje stoppet med en feilmelding: du kan ikke skjøte en tekst og et tall med plusstegnet.

Legg merke til siste uttrykk. str(100) er teksten "100", som har tre
tegn. Det er en grei måte å telle sifre på uten å regne.

✏️Eksempel 2: `fjern_tegn` — mønstereksempelet i sjanger E

Skriv fjern_tegn(tekst, tegn) som returnerer en ny tekst lik tekst, men uten forekomster av tegn. Vis hva funksjonen gjør med en tom tekst, og med en tekst der alt skal fjernes.

Mønsteret flyttes rett inn i en funksjon:

def fjern_tegn(tekst, tegn):
    ny = "" for t in tekst:
        if t != tegn:
            ny = ny + t return ny

print(fjern_tegn("bibliotek", "i"))
print(fjern_tegn("aaa", "a"))
print(len(fjern_tegn("aaa", "a")))

Utskrift:

bblotek

0

Legg merke til at andre kall ikke skriver noe synlig: resultatet er den tomme
teksten, og en tom tekst ser ut som ingenting. Tredje linje beviser at den likevel er der, med lengde 0 — og ikke None.

Slik ville sensor sett på det: fire ting gir uttelling hver for seg. Den tomme
teksten før løkka, løkka over tegnene, !=-betingelsen som slipper gjennom alt annet, og return etter løkka. Har du de tre første, men glemt return, er strukturen på plass og trekket lite — men funksjonen gir None, og alt som bygger videre, faller sammen.

Merk at parameteren heter tegn og løkkevariabelen t. Hadde begge hett
tegn, ville løkka overskrevet det du lette etter allerede på første runde, og funksjonen ville sammenlignet hvert tegn med seg selv. Det er en stille feil som alltid returnerer den tomme teksten.

📝Oppgave 3
Eksamensnivå, sjanger E

En resirkuleringsstasjon skanner koder der bare sifrene betyr noe. Skriv funksjonen
bare_sifre(tekst) som returnerer en ny tekst med bare sifrene fra tekst, i samme rekkefølge.

a) Skriv funksjonen med tegn-for-tegn-mønsteret.

b) Hva returnerer bare_sifre("abc"), og hva er lengden på svaret?

c) Hvorfor kan du ikke returnere et tall i stedet?

📝Oppgave 4
Eksamensnivå, sjanger E

Skriv funksjonen
snu(tekst) som returnerer teksten baklengs.

a) Skriv funksjonen med en løkke over plassene, bakfra.

b) Skriv den samme funksjonen med en løkke over tegnene, uten indekser.

c) Hvilken av de to ville du levert på eksamen?

Løkke 3 — Å dele opp en tekst: .split() og .rstrip() (~12 min)

Nå kommer de to metodene som gjør resten av faget mulig. Alt som kommer inn utenfra — en linje fra en fil, en linje brukeren skriver — er én lang tekst med flere opplysninger i. Å dele den opp riktig er første steg i hver eneste filoppgave.

`.split()` uten argument

Deler teksten i en liste av ord, på hvert mellomrom:

setning = "buss tog trikk" print(setning.split())
print(len(setning.split()))
print(setning.split()[0])

Utskrift:

['buss', 'tog', 'trikk']
3 buss

Resultatet er en helt vanlig liste, med alt du kan gjøre med lister fra
kap. 3.1: indeksering, len, og en for-løkke over elementene.

Merk skrivemåten: setning.split() med punktum foran og tomme parenteser etter.
Det er en metode — en funksjon som hører til teksten den står bak — samme form som liste.append(...).

Uten argument deler .split() på ett eller flere blanktegn, og den kaster tomme biter. "a b".split() gir derfor to elementer, ikke fire.

`.split(skilletegn)`

Med et argument deler den på nøyaktig det tegnet du oppgir:

linje = "Ada;19;Oslo" felt = linje.split(";")
print(felt)
print(felt[0], felt[1])
print(int(felt[1]) + 1)

Utskrift:

['Ada', '19', 'Oslo']
Ada 19
20

Dette er formen filoppgavene bruker: én linje inneholder flere felt, skilt av semikolon, komma eller kolon.

Legg merke til siste linje. Feltene er alltid tekster, også når de ser ut som tall. Skal du regne med et felt, må det gjennom int(...) først — det er feilkode #4, og den rammer alle som glemmer det.

Oppgi du feil skilletegn, får du én stor bit i stedet for flere små:
"Ada;19".split(",") gir ['Ada;19']. Da er feilen ikke en feilmelding, men et galt svar lenger nede. Det er feilkode #8.

`.rstrip()` og `.strip()`

Fjerner blanktegn i endene og gir en ny tekst. .rstrip() fjerner bare til høyre; .strip() fjerner i begge ender:

linje = "Ada;19\n" print(len(linje))
print(len(linje.rstrip()))
print(linje.rstrip().split(";"))
print("  ada  ".strip())

Utskrift:

7
6
['Ada', '19']
ada

Tegnet \n i første linje er linjeskiftet — ett enkelt tegn, ikke to, slik lengden 7 viser. Det henger med hver eneste linje du leser fra en fil, og det er nettopp det .rstrip() er til for.

Rekkefølgen er alltid .rstrip() FØR .split(). Snur du den, deler du opp
en tekst som fortsatt har linjeskiftet i seg, og det siste feltet blir feil.

✏️Eksempel 3: Fra én linje til ferdige verdier

En frivilligsentral har medlemslinjer på formen "Ada;19;Oslo", med et linjeskift på slutten slik de kommer fra en fil. Skriv les_medlem(linje) som returnerer navnet som tekst og alderen som tall, og vis at alderen faktisk kan regnes med.

Rens først, del så, konverter til slutt:

def les_medlem(linje):
    felt = linje.rstrip().split(";")
    navn = felt[0]
    alder = int(felt[1])
    return navn, alder

n, a = les_medlem("Ada;19;Oslo\n")
print(n, a)
print(a + 1)
print(len(n))

Utskrift:

Ada 19
20
3

Dette er malen for hver eneste filoppgave i faget, og den er verdt å lære
utenat i akkurat denne rekkefølgen:

1. .rstrip() — fjern linjeskiftet.
2. .split(skilletegn) — del i felt.
3. int(...) på de feltene som skal være tall.

Slik ville sensor sett på det: hvert av de tre stegene gir uttelling for seg.
Glemmer du int(...), får du en funksjon som returnerer "19" i stedet for
19 — riktig struktur, én type feil, lite trekk. Glemmer du .rstrip(), virker alt tilsynelatende, helt til noe skal sammenlignes.

Legg merke til at funksjonen bruker flere returverdier fra
kap. 2.1, og at len(n) er 3 — navnet har ingen usynlige tegn hengende ved seg.

📝Oppgave 5
Eksamensnivå, sjanger E

En kollektivrute er beskrevet som "Majorstuen-Nationaltheatret-Jernbanetorget", med bindestrek mellom stoppene. Skriv funksjonen antall_stopp(rute) som returnerer hvor mange stopp ruta har.

a) Skriv funksjonen.

b) Hva returnerer antall_stopp("Blindern")?

c) En kollega foreslår å telle bindestreker i stedet, og legge til én. Gir
det samme svar? Nevn ett tilfelle der de to metodene er uenige.

📝Oppgave 6
Eksamensnivå, sjanger A

Hva skriver programmet ut? Skriv utskriften nøyaktig, med mellomrom og linjeskift slik terminalen viser den.

linje = "sykkel:12:rod\n" felt = linje.split(":")
print(len(felt))
print(felt[0], felt[1])
print(felt[2] == "rod")
rent = linje.rstrip().split(":")
print(rent)
print(int(rent[1]) * 2)

Løkke 4 — Å lete i en tekst (~10 min)

Siste bit er de to spørsmålene du oftest stiller en tekst: finnes dette i den? og hvordan ser den ut uten store og små bokstaver?

`del in tekst`

Svarer True eller False på om en delstreng finnes i teksten:

tekst = "kollektivtrafikk" print("trafikk" in tekst)
print("Trafikk" in tekst)
print("t" in tekst)
print("ki" in tekst)

Utskrift:

True
False
True
False

Merk to ting. Testen skiller stor og liten bokstav — andre linje er usann bare fordi T er stor. Og tegnene må stå etter hverandre og i riktig rekkefølge:
"ki" finnes ikke, selv om både k og i gjør det hver for seg. ("kt" ville derimot gitt True, fordi de to står inntil hverandre i kollektiv.)

in forteller om delen finnes, ikke hvor. Trenger du plassen, teller du deg fram med en indeksløkke, slik du gjorde med lister.

`.lower()` og `.upper()`

Gir en ny tekst med bare små eller bare store bokstaver. Den opprinnelige er urørt:

navn = "Ada Berg" print(navn.lower())
print(navn.upper())
print(navn)
print("ADA".lower() == "ada")

Utskrift:

ada berg
ADA BERG
Ada Berg
True

Den vanligste bruken er å sammenligne uten å bry seg om store bokstaver: gjør begge sider små først, og sammenlign så.

Merk at metodene returnerer en ny tekst. Skriver du bare navn.lower() på en linje for seg, kastes resultatet og navn er uendret — samme felle som med alt annet som returnerer noe.

✏️Eksempel 4: En full Oppgave 3-oppgave i sjanger E

En kantine har dagens meny som én tekst: "suppe fisk salat suppe". Skriv
antall_med_forbokstav(setning, bokstav) som teller hvor mange ord i setningen som begynner på den gitte bokstaven. Funksjonen skal tåle en tom setning.

Del i ord, og se på det første tegnet i hvert:

def antall_med_forbokstav(setning, bokstav):
    antall = 0 for ord_tekst in setning.split():
        if ord_tekst[0] == bokstav:
            antall = antall + 1 return antall

print(antall_med_forbokstav("suppe fisk salat suppe", "s"))
print(antall_med_forbokstav("suppe fisk salat suppe", "f"))
print(antall_med_forbokstav("", "s"))

Utskrift:

3
1
0

Slik ville sensor sett på det, steg for steg. .split() gir ordene (2 p),
tellermønsteret rundt (2 p), ord_tekst[0] som forbokstav (1 p) og return etter løkka (1 p). Har du strukturen, men sammenlignet med bokstav uten å ta hensyn til store bokstaver, er det en liten feil med riktig idé — og verdt å nevne i en kommentar hvis oppgaveteksten er uklar.

Den tomme setningen løses av seg selv. "".split() gir den tomme lista, så
løkka kjører null runder og telleren returneres som 0. Det er verdt å legge merke til: hadde du i stedet gått tegn for tegn og sett etter mellomrom, måtte du håndtert det tilfellet selv.

Én skjult forutsetning bør nevnes. Koden skriver ord_tekst[0] uten å sjekke
at ordet har tegn. Det er trygt her, fordi .split() aldri gir tomme ord — men hadde du delt med .split(";"), kunne du fått et tomt felt, og da ville
ord_tekst[0] stoppet programmet. Slike forutsetninger skriver du en kort kommentar om i besvarelsen.

📝Oppgave 7
Eksamensnivå, sjanger E

En frivilligsentral vil vise medlemmene med initialer. Skriv funksjonen
initialer(navn) som returnerer forbokstaven i hvert ord, med et punktum etter hver.

For "Ada Marie Berg" skal funksjonen gi "A.M.B.".

a) Skriv funksjonen.

b) Hva returnerer initialer("")?

c) Utvid funksjonen slik at initialene alltid blir store bokstaver, uansett
hvordan navnet er skrevet.

📝Oppgave 8
Eksamensnivå, sjanger I

En student skal fjerne alle mellomrom fra en tekst. Hun leverer:

def fjern_mellomrom(tekst):
    ny = "" for tegn in tekst:
        if tegn != " ":
            ny + tegn return ny

a) Hva returnerer fjern_mellomrom("bruker navn")?

b) Gi et konkret moteksempel og forklar i én setning hvorfor det går galt.

c) Rett feilen, og vis at den rettede funksjonen virker.

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.

Tegn

Ett enkelt symbol i en tekst: en bokstav, et siffer, et mellomrom, et komma eller et linjeskift.

I Python finnes ingen egen datatype for ett tegn. tekst[0] gir en tekst av lengde 1, og den kan alt en tekst kan — den kan sammenlignes, skjøtes og sendes til en funksjon.

Det er derfor sifferbetingelsen tegn >= "0" and tegn <= "9" fungerer: du sammenligner to tekster, ikke to tall.

Den tomme teksten

Teksten "", med lengde 0.

Den er startpunktet i tegn-for-tegn-mønsteret, og den er svaret når en funksjon ikke fant noe å ta med. En tom tekst ser ut som ingenting når den skrives ut, og det forveksles lett med at funksjonen ikke returnerte noe.

Skillet er viktig: "" er en tekst med lengde 0, mens None betyr at det ikke kom noen verdi tilbake i det hele tatt.

Streng-literal

En tekst skrevet rett inn i koden, mellom anførselstegn: "sykkel".

Enkle og doble anførselstegn virker likt i Python. Boka bruker doble, og det gjør fagets løsningsforslag også — men når Python skriver ut en tekst som ligger inne i en liste eller ordbok, viser den den med enkle.

Den forskjellen er ren utskriftsform, ikke to ulike verdier. Men i et auto-rettet svarfelt må du gjengi den slik terminalen faktisk viser den.

Sammenligning av tekst

Tekster sammenlignes tegn for tegn etter rekkefølgen i tegnsettet, ikke etter lengde.

I praksis betyr det at store bokstaver kommer før små, og at sifrene står samlet før bokstavene. Derfor er "Z" < "a" sann, og derfor virker
tegn >= "0" and tegn <= "9" som en siffertest.

Skal du sammenligne uten å bry deg om store bokstaver, gjør begge sider små med
.lower() først.

Blanktegn

Fellesordet for mellomrom, tabulator og linjeskift — tegnene som ikke vises, men som teller med i lengden.

.split() uten argument deler på blanktegn, og .strip() og .rstrip() fjerner dem i endene.

De er kilden til de fleste stumme feilene i faget: to tekster som ser like ut på skjermen, kan skille seg med ett usynlig tegn — og da svarer sammenligningen
False uten at noe ser galt ut.

Linjeskift

Tegnet som avslutter en linje. I Python skrives det \n inne i en tekst, og det er ett tegn, ikke to.

Hver linje du leser fra en fil, har det på slutten. Derfor er .rstrip() det første du gjør med en innlest linje, hver eneste gang.

Du ser det aldri i en utskrift — der viser det seg bare som at teksten fortsetter på neste linje.

Metode

En funksjon som hører til verdien den står bak, skrevet med punktum mellom:
tekst.split(), tekst.rstrip(), liste.append(e).

Skrivemåten forteller hvem som gjør jobben. len(tekst) er en vanlig funksjon som får teksten inn; tekst.split() er en metode som teksten selv utfører.

Senere i boka skriver du dine egne metoder, på dine egne klasser. Formen med punktum blir da den samme — og det er ingen tilfeldighet.

Å ta imot resultatet

Metodene i dette kapitlet deler seg i to grupper, og forskjellen koster poeng.

.split(), .rstrip(), .strip(), .lower() og .upper() returnerer en ny verdi og lar originalen være urørt. De må tas imot:
ren = linje.rstrip().

liste.append(e) endrer lista og returnerer ingenting. Den skal ikke tas imot — liste = liste.append(e) ødelegger lista.

Regelen: er verdien uforanderlig, får du en ny; kan den endres, blir den endret.

Felt

En av bitene du får når du deler en linje: i "Ada;19;Oslo" er "Ada", "19" og "Oslo" de tre feltene.

Feltene er alltid tekster, også når de ser ut som tall. Skal du regne med et felt, må det gjennom int(...) — det er feilkode #4.

Rekkefølgen er fast og bestemt av dataformatet, så du henter dem med indeks:
felt[0] er navnet, felt[1] alderen. Skriv gjerne en kommentar om hvilket felt som er hva; det gjør besvarelsen lettere å rette.

Tegn-for-tegn-mønsteret

Å bygge en ny tekst med ny = "" før løkka, ny = ny + tegn inne i den og
return ny etter.

Kjenn det igjen på oppgaveteksten: «fjern alle …», «lag en ny tekst der …»,
«behold bare …», «snu …».

Det er samme skjelett som bygg-en-ny-liste-mønsteret, med "" i stedet for [] og plusstegn i stedet for append. Ser du de to som ett mønster med to varianter, har du dekket halve sjanger C og hele sjanger E.

Å gå bakfra
for i in range(len(tekst) - 1, -1, -1): går gjennom plassene fra siste til første.

De tre tallene er lette å bomme på: start er len(tekst) - 1, stopp er -1 fordi stoppverdien aldri er med, og steget er -1.

Trenger du bare å snu teksten, finnes det en enklere vei: bygg foran med
ny = tegn + ny i en vanlig løkke. Da har du ingen grenser å skrive feil.

`.split()` gir en liste

Resultatet av .split() er en helt vanlig liste, ikke en tekst.

Det betyr at alt fra kap. 3.1 gjelder: len(...) gir antall biter, felt[0] gir den første, og for del in tekst.split(): går gjennom dem.

Nettopp derfor kommer strengekapitlet etter listekapitlet. Uten lister ville
.split() ikke hatt noe å levere resultatet i.

Tekst mot tall

De to typene ser like ut i en utskrift, men oppfører seg helt ulikt.

"12" + "3" gir "123"; 12 + 3 gir 15. "12" * 2 gir "1212"; 12 * 2 gir 24. Og "12" == 12 er usann — de er ikke samme verdi.

Alt som kommer inn utenfra, er tekst: det brukeren skriver, og hver linje fra en fil. Konverteringen med int(...) er derfor ikke en detalj, men første steg i enhver oppgave med data utenfra.

Skilletegn

Tegnet du deler en linje på: semikolon, komma, kolon eller mellomrom.

Skilletegnet er en del av dataformatet, ikke noe du velger fritt. Leser du en fil, må du bruke det tegnet fila faktisk bruker — oppgir du feil, får du én stor bit i stedet for flere små, og feilen er stum.

Er du usikker på formatet i en eksamensoppgave, skriv en kommentar om hvilket skilletegn du har forutsatt. Det er den ene legitime bruken av kommentarer i en besvarelse.

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.