Unicode
Unicode og ordinaler
Som alle andre datatyper i Python er også strenger egentlig representert under panseret som en sekvens av 0 og 1. For eksempel representeres bokstaven 'A'
som 1000001
og bokstaven 'B'
som 1000010
. Hvis vi i stedet for å tolke sekvensen av 0 og 1 som en bokstav later som sekvensen er et tall i totall-systemet, får vi henholdsvis 65 for 'A'
og 66 for 'B'
.
På denne måten er hvert eneste symbol (bokstav og tegn, emoji og andre symboler som kan opptre i en streng) knyttet til et tall. Dette tallet kalles en ordinal for symbolet. Hvordan symboler matcher ordinaler gjøres (nå) på en standardisert måte som kalles Unicode. Unicode er med andre ord en matching mellom ordinal og symbol. Under viser vi et lite utdrag.
Ordinal | Symbol |
---|---|
65 | 'A' |
66 | 'B' |
67 | 'C' |
… | … |
90 | 'Z' |
198 | 'Æ' |
216 | 'Ø' |
197 | 'Å' |
Ordinal | Symbol |
---|---|
97 | 'a' |
98 | 'b' |
99 | 'c' |
… | … |
122 | 'z' |
230 | 'æ' |
248 | 'ø' |
229 | 'å' |
Ordinal | Symbol |
---|---|
9 | '\t' (tab) |
10 | '\n' (linjeskift) |
32 | ' ' (mellomrom) |
33 | '!' |
48 | '0' |
49 | '1' |
50 | '2' |
128013 | '🐍' |
For å finne ordinalen til et symbol kan vi bruke funksjonen ord
:
symbol = 'A'
ordinal = ord(symbol)
print('Ordinal til', symbol, 'er' , ordinal) # Ordinal til A er 65
For å konvertere fra ordinal til symbol («character») kan vi bruke funksjonen chr
:
ordinal = 97
symbol = chr(ordinal)
print('Ordinal', ordinal, 'har symbol', symbol) # Ordinalen 97 har symbol a
Tekstkoding
Ett symbol kan representeres som ett tall, som vist i forrige avsnitt. Men hva om det er flere symboler etter hverandre, som i en streng eller en fil med tekst? Fordi det ikke eksisterer noe naturlig «mellomrom» i noe som representeres som en sekvens av 0 og 1, må vi bestemme oss for noen regler for å skille hvor ett symbol slutter fra hvor det neste starter.
Det finnes flere ulike strategier for dette, som vi kaller koding av en streng (engelsk: encoding). Kodinger som støtter alle Unicode-symboler begynner med «UTF» (Unicode Transformation Format).
Eksempler på kodinger:
ASCII er en gammel standard som Unicode-ordinalene er bakoverkompatibel med. Den deler opp sekvensen av 0’er og 1’ere i blokker på akkurat 8 biter, og så tolker den hver blokk som en ordinal oppgitt i totallsystemet. Hver blokk begynner alltid med 0. Eksempler noen ulike symboler og hvordan de kodes i ASCII:
Symbol | Unicode | Koding i ASCII |
---|---|---|
\n | 10 | 00001010 |
A | 65 | 01000001 |
B | 66 | 01000010 |
Æ | 198 | ikke støttet |
🐍 | 128013 | ikke støttet |
Den delen av kodingen som er markert i gult over er selve ordinalen (i totallsystemet). Nullene som kommer foran dette bare fyller opp plassen slik at blokken får størrelse på 8 bit.
-
Fordeler med ASCII: lett å forstå og implementere. Bruker lite lagringsplass. Støttes også av svært gamle systemer.
-
Ulemper med ASCII: Støtter kun symboler med unicode-ordinal under 128. Altså ingen støtte for norske bokstaver æ, ø og å.
UTF-32 er en koding som er enkel å forstå (men som i praksis er lite brukt). Den deler opp sekvensen av 0’er og 1’ere i blokker på akkurat 32 biter, og så tolker den hver blokk som en ordinal oppgitt i totallsystemet (akkurat som ASCII, altså, men tar større plass). Eksempler noen ulike symboler og hvordan de kodes i UTF-32:
Symbol | Unicode | Koding i UTF-32 |
---|---|---|
\n | 10 | 00000000000000000000000000001010 |
A | 65 | 00000000000000000000000001000001 |
B | 66 | 00000000000000000000000001000010 |
Æ | 198 | 00000000000000000000000011000110 |
🐍 | 128013 | 00000000000000011111010000001101 |
Den delen av kodingen som er markert i gult over er selve ordinalen (i totallsystemet). Nullene som kommer foran dette bare fyller opp plassen slik at blokken får størrelse på 32 bit.
-
Fordeler med UTF-32: lett å forstå og implementere. Man kan raskt finne ut hvilken bokstav som er i en gitt posisjon. Støtter alle Unicode-symboler.
-
Ulemper med UTF-32: bruker mye unødvendig lagringsplass. Ikke bakoverkompatibel med ASCII.
UTF-8 er den vanligste unicode-kodingen. Den deler opp sekvensen av 0’er og 1’ere i blokker på 8 biter; de vanligste symbolene bruker bare én slik blokk, mens de mer sjeldne bruker flere blokker. Eksempler på hvordan noen ulike symboler blir kodet i UTF-8:
Symbol | Unicode | Koding i UTF-8 |
---|---|---|
\n | 10 | 00001010 |
A | 65 | 01000001 |
B | 66 | 01000010 |
Æ | 198 | 11000011 10000110 |
🐍 | 128013 | 11110000 10011111 10010000 10001101 |
Den delen av kodingen som er markert i gult over er selve ordinalen (i totallsystemet). Den delen av kodingen som er markert i rødt inneholder informasjon som UTF-8 bruker for å avgjøre hvor mange blokker symbolet består av. De øvrige nullene bare fyller opp plassen slik at hver blokk får en størrelse på 8 bit.
- Fordeler med UTF-8: Er bakoverkompatibel med den eldre standarden ASCII. Bruker mindre lagringsplass enn UTF-16 og UTF-32. Støtter alle Unicode-symboler. Benyttes nå som standard på internett.
Når man leser eller skriver en tekstfil, må man velge hvilken koding man skal benytte.
- For å skrive til fil er valget enkelt: du bør alltid velge UTF-8 med mindre du har helt spesielle grunner til å gjøre noe annet (f. eks. kompabilititet med et gammelt system).
- For å lese fra en fil må du vite hvilken koding som ble brukt da filen ble lagret. Med 95% sannsynlighet er dette UTF-8, men av og til kan det være noe annet. Hvis du ikke vet, kan du prøve å gjette deg frem. Hvis du får rare tegn i stedet for norske bokstaver, er det sannsynligvis fordi du har gjettet feil. Da må du prøve å gjette på en annen koding.
Hvis du ikke vet hvilken koding som er brukt, prøv disse ekodingene først: UTF-8 (anbefalt), Windows-1252 (også kalt cp1252), ISO 8859-1 (også kalt Latin-1), Windows-1251 (også kalt cp1251), UTF-16 og UTF-32. Hvis teksten er på et spesielt språk kan du også søke på internett etter kodinger som er vanlige for det språket.
# Eksempel på å skrive til en fil
writing_text = "Dette er en tekst. Den har æøå og 🐍 i seg."
with open("myfile.txt", "w", encoding="utf-8") as f:
f.write(writing_text)
# Eksempel på å lese fra en fil
with open("myfile.txt", "r", encoding="utf-8") as f:
reading_text = f.read()
print(reading_text) # Dette er en tekst. Den har æøå og 🐍 i seg.
Dersom du ikke angir noe for
encoding=
vil Python bruke standarden for ditt operativsystem. Dette er vanligvisutf-8
på Mac og Linux, ogcp1252
på Windows, men kan også variere basert på «locale» -konfigurasjonen av operativsystemet (språk, etc.). Det er derfor lurt å alltid spesifisereencoding=
når du skriver til/leser fra filer, slik at du ikke får problemer når du bytter operativsystem.