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.
sjanger: E — skriv en funksjon over en streng, verdt 4–7 poeng inne i
Oppgave 3. Typiske bestillinger er «fjern alle …», «tell hvor mange …» og «lag en ny tekst der …».
Men strengene betyr mer enn de 83 prosentene. Alt som kommer inn i et program utenfra, er tekst: det brukeren skriver, og hver linje du leser fra en fil.
Uten .split() og .rstrip() kommer du ikke i gang med filbehandlingen, som er en fast del av den store Oppgave 4.
Dette må sitte — bokas høyeste av tre nivåer for selve strenghåndverket. To
feil koster nesten alle poengene: #8, glemt .rstrip() eller feil separator i .split(), og forsøket på å endre en tekst på plass, som ikke går an.
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 poengI 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.
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 lTellingen 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.
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
42De 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.
Gir antall tegn, medregnet mellomrom og tegnsetting:
navn = "Ada" print(len(navn), len(""), len("to ord"))Utskrift:
3 0 6Merk 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.
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:
2Dette 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 medtekst[i].
Valget er nøyaktig det samme som for lister, og svaret på det samme spørsmålet:
trenger du plassen?
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 silLegg 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.
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 32Tre 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.
(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"?
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.
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:
olletivtrafiDet 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.
+ 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 2Merk 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.
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! 3Uten 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.
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
0Legg 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 hetttegn, 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.
En resirkuleringsstasjon skanner koder der bare sifrene betyr noe. Skriv funksjonenbare_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?
Python har ferdige metoder som løser flere av oppgavene i dette kapitlet på én linje: tekst.replace(a, b) bytter ut, tekst.count(a) teller,tekst.find(a) finner plassen, "".join(liste) skjøter en liste til en tekst, og tekst[::-1] snur den.
Denne boka bruker dem ikke, og det er et bevisst valg. Fagets egne
løsningsforslag skriver den eksplisitte løkka, fordi det er løkka som er ferdigheten kurset måler — og fordi den samme løkka er det du trenger inne i en metode i den store Oppgave 4, der ingen ferdig metode passer.
De fire metodene boka bruker, er .split(), .rstrip(), .strip(),.lower() og .upper(). De er med fordi de gjør noe du ikke rimeligvis kan skrive selv på en eksamen, og fordi filbehandlingen er avhengig av dem.
Skriv funksjonensnu(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.
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 bussResultatet 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.
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
20Dette 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.
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']
adaTegnet \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.
Feilen er stum: programmet krasjer ikke, det svarer bare galt.
linje = "Ada;19\n" uten = linje.split(";")
print(uten)
print(uten[1] == "19")
med = linje.rstrip().split(";")
print(med)
print(med[1] == "19")Utskrift:
['Ada', '19\n']
False
['Ada', '19']
TrueSe på de to listene. De ser nesten like ut, men det siste feltet i den første har linjeskiftet klistret på seg — og derfor er sammenligningen med"19" usann.
Det er verre enn en feilmelding, fordi feilen dukker opp langt unna: en sammenligning som aldri slår til, en nøkkel som ikke finnes i ordboka, et navn som ser riktig ut i utskriften men ikke matcher.
Regelen som holder: les linja, .rstrip() den med én gang, og del deretter.
Alltid i den rekkefølgen.
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
3Dette 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 for19 — 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.
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.
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?
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
FalseMerk 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.
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
TrueDen 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.
En kantine har dagens meny som én tekst: "suppe fisk salat suppe". Skrivantall_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
0Slik 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 villeord_tekst[0] stoppet programmet. Slike forutsetninger skriver du en kort kommentar om i besvarelsen.
En frivilligsentral vil vise medlemmene med initialer. Skriv funksjoneninitialer(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.
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 nya) 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.
Fem feil koster nesten alle poengene som mistes på strenger:
- #8 — glemt .rstrip(). Linjeskiftet henger igjen i det siste feltet, og
sammenligninger som «ser riktige ut», svarer False. Rens før du deler.
- #8 — feil skilletegn i .split(). Du får én stor bit i stedet for flere
små, og feilen dukker opp langt unna.
- #4 — glemt int(...). Felter fra .split() er alltid tekster, også når de
ser ut som tall.
- Forsøk på å endre en tekst på plass. tekst[0] = "s" stopper programmet.
Bygg en ny tekst i stedet.
- Resultatet ikke tatt imot. ny + tegn og tekst.lower() returnerer nye
verdier. Uten en tilordning kastes de.
Og én retningsfelle: ny = ny + tegn bygger forfra, ny = tegn + ny bygger bakfra. Les hvilken vei du bygger før du sporer.
Begrepsbank
Begrepsbanken er flashcard- og repetisjonsstoff — den gjentar det du nettopp har lest. Hopp trygt over ved førstegangslesing; tidsanslaget for kapitlet gjelder kjernestoffet.
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.
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.
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.
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 virkertegn >= "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.
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 sammenligningenFalse uten at noe ser galt ut.
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.
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.
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.
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.
Å bygge en ny tekst med ny = "" før løkka, ny = ny + tegn inne i den ogreturn 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.
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 medny = tegn + ny i en vanlig løkke. Da har du ingen grenser å skrive feil.
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.
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.
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.
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.