En streng er en sekvens av tegn som vi kan indeksere og dele opp (slicing). Python har et rikt utvalg av strengmetoder for søk, erstatning og formatering. Strenger er uforanderlige (immutable), så hver operasjon lager en ny streng.
Læringsmål
01Indeksere strenger med både positive og negative indekser, og forklare hvorfor tellingen starter på null
02Bruke slicing (start:slutt:steg) til å skjære ut delstrenger, og begrunne hvorfor sluttindeksen ikke er med
03Forklare at strenger er uforanderlige og vise hvordan «endringer» i praksis lager en ny streng
04Velge riktig strengmetode (upper, strip, find, replace, split, join) til en gitt oppgave og vite hvilken type metoden returnerer
Skriv navn = "Python" i et Python-program, og du har laget en streng. Be så om navn[0], og du får tilbake "P". Be om navn[1], og du får "y". En streng er rett og slett en ordnet rekke av tegn, der hvert tegn har en fast plass. Den plassen kaller vi en indeks, og indeksering er det å hente ut tegnet på en bestemt indeks.
Det første som overrasker mange er at tellingen starter på null. Tegnet på indeks 0 er det første tegnet, indeks 1 er det andre, og så videre. Strengen "Python" har seks tegn, så gyldige indekser er 0 til og med 5. Ber du om navn[6], krasjer programmet med en IndexError, fordi det ikke finnes noe sjette-fra-null tegn.
Python lar deg også telle bakfra med negative indekser. navn[-1] er det siste tegnet, "n", navn[-2] er det nest siste, "o". Negative indekser er praktiske når du vet hvor langt fra slutten noe ligger, men ikke gidder å regne ut den totale lengden. Lengden får du forresten med len(navn), som her gir 6.
FIGTegnene i "Python" med positive og negative indekser
Figuren over viser hvordan tegnene i "Python" ligger i hver sin celle. Legg merke til at de positive indeksene under cellene går fra venstre mot høyre fra null, mens de negative går fra høyre mot venstre fra -1. Begge peker på de samme cellene, bare fra hver sin kant.
Slicing — å skjære ut en bit
Ofte vil du ikke ha ett enkelt tegn, men en sammenhengende bit av strengen. Det kaller vi slicing, og skrivemåten er navn[start:slutt]. Resultatet er en ny streng som inneholder tegnene fra og med indeks start, men ikke med indeks slutt. Den øvre grensen er altså med vilje utelatt.
Et eksempel: "Python"[0:3] gir "Pyt". Vi får tegnene på indeks 0, 1 og 2, men ikke 3. Dette virker rart første gang, men det har en grunn: lengden på utsnittet blir alltid slutt - start. 0:3 gir tre tegn, 2:5 gir tre tegn. Du slipper å justere med pluss og minus én.
Begge grensene kan utelates. "Python"[:3] betyr «fra begynnelsen til indeks 3» og gir "Pyt". "Python"[3:] betyr «fra indeks 3 til slutten» og gir "hon". Og "Python"[:] gir hele strengen tilbake. En vanlig snarvei er "Python"[-3:], som gir de tre siste tegnene, "hon".
Du kan også oppgi et tredje tall, et steg: navn[start:slutt:steg]. Med "Python"[::2] hopper du over annethvert tegn og får "Pto". Og det berømte trikset "Python"[::-1] snur strengen og gir "nohtyP", fordi et negativt steg går baklengs.
FIGSlicing: utsnittet [0:3] av "Python"
Figuren fremhever utsnittet [0:3] i "Python". Tenk på grensene som streker mellom cellene heller enn på dem: streken før indeks 0 og streken før indeks 3 klemmer ut nettopp tre tegn.
Strenger er uforanderlige
Her kommer et poeng som biter mange nybegynnere: strenger har immutabilitet. Det betyr at en streng aldri kan endres etter at den er laget. Prøver du navn[0] = "J" for å gjøre "Python" om til "Jython", får du en TypeError. Tegnene ligger fast.
Hva gjør man da? Man lager en ny streng. Alle operasjoner som «endrer» en streng, returnerer egentlig en helt ny streng og lar originalen være i fred:
Dette er ikke en svakhet, men et bevisst designvalg. Fordi strenger ikke kan endres bak ryggen din, kan Python trygt dele og gjenbruke dem internt, og du kan bruke dem som nøkler i en dictionary uten å bekymre deg for at de plutselig skifter verdi. Husk bare alltid: hvis du vil beholde resultatet av en strengoperasjon, må du ta vare på returverdien i en variabel. navn.upper() alene gjør ingenting nyttig hvis du ikke fanger opp svaret.
Strengmetoder — det rike verktøyskrinet
En strengmetode er en funksjon som hører til en streng, og som du kaller med punktum-skrivemåten streng.metode(). Python har et stort utvalg av dem, og de dekker det meste du trenger til søk, opprydding og omforming av tekst. Fordi strenger er uforanderlige, lager alle metodene som «endrer» tekst en ny streng — originalen står urørt.
De mest brukte faller i noen grupper. For store og små bokstaver har du upper(), lower() og capitalize(). For å fjerne uønsket luft har du strip(), som klipper bort mellomrom og linjeskift i begge ender — uvurderlig når du leser inn tekst fra en bruker. For å lete har du find(), som gir indeksen der et delstreng starter (eller -1 hvis det ikke finnes), og replace(), som bytter ut alle forekomster av et delstreng med et annet.
To metoder fortjener ekstra oppmerksomhet fordi de er hverandres motsetninger. split() deler en streng opp i en liste av delstrenger ved et skilletegn: "a,b,c".split(",") gir ["a", "b", "c"]. join() gjør det motsatte og limer en liste av strenger sammen med en skillestreng: ",".join(["a", "b", "c"]) gir "a,b,c". Legg merke til at join kalles på skillestrengen, ikke på listen — det er en vanlig snublestein.
Hver metode returnerer en ny verdi uten å endre originalen. Merk typene: len og find gir tall, split gir en liste, startswith gir en bool, og resten gir strenger.
Snutten over samler de mest sentrale metodene. Studer hvordan hver linje produserer en ny verdi, og hvordan vi alltid fanger den opp i en variabel eller skriver den ut. Et nyttig spørsmål å stille deg ved hver metode: returnerer denne en streng, et tall, en liste eller en sannhetsverdi? len() og find() gir tall, split() gir en liste, startswith() gir en bool, mens upper() og strip() gir strenger.
Å sette sammen tekst
Strenger kan slås sammen med +, det vi kaller konkatenering: "god" + "dag" gir "goddag". Du kan også gjenta en streng med *: "ha" * 3 gir "hahaha". Men når du skal flette inn tall eller variabler i en tekst, er konkatenering tungvint, fordi du må konvertere tall til streng med str() først. Da er f-strenger langt ryddigere: f"Hei {navn}, du er {alder} år" setter inn verdiene av navn og alder direkte. F-strenger møtte vi i kapittelet om inn- og utdata, og de spiller godt sammen med alt du nå kan om strenger.
Et ord om søk og tilhørighet før vi runder av delen. Operatoren in sjekker om et delstreng finnes i en streng: "th" in "Python" gir True. Dette er ofte enklere enn find() når du bare vil vite om noe er der, og ikke hvor.
Å løpe gjennom en streng
Fordi en streng er en sekvens, kan du gå gjennom den med en for-løkke, akkurat som du senere skal gjøre med lister. Den enkleste formen gir deg ett tegn om gangen:
python
ord = "Python"fortegninord:
print(tegn)
Trenger du både tegnet og indeksen, er enumerate smart, fordi du da slipper å telle selv:
Slike gjennomløp er ryggraden i tekstbehandling: tell hvor mange ganger en bokstav forekommer, bygg opp en ny streng tegn for tegn, eller sjekk hvert tegn mot en betingelse. Husk fra forrige avsnitt at du ikke kan endre tegnene på plass — vil du «redigere» en streng i en løkke, bygger du heller opp en ny streng underveis med konkatenering, og lar originalen være.
Et praktisk eksempel
Tenk deg at en bruker skriver inn et navn med tilfeldig bruk av store og små bokstaver og litt ekstra mellomrom, og du vil rydde det til pent format. Da kombinerer du flere av verktøyene over:
Her fjerner strip() mellomrommene i endene, title() gjør første bokstav i hvert ord stor og resten små, og slicing henter ut fornavnet. Legg merke til at vi lenker metodene etter hverandre: rå.strip().title() kjører først strip() på rå, og kaller så title() på resultatet. Slik kjeding er mulig nettopp fordi hver metode gir tilbake en ny streng vi kan kalle neste metode på.
Sammen med slicing, indeksering og metodene danner dette et komplett sett med verktøy for å plukke fra hverandre, lete i og bygge opp tekst — selve råstoffet i nesten all programmering som har med mennesker å gjøre.
Mine notater
Skriv egne notater for dette kapittelet. De lagres automatisk og dukker opp i «Mine notater»-oversikten paa fag-siden.