Tilbake
1.1

1.1 Variabler, datatyper, uttrykk og operatorpresedens

Tall, boolske verdier, aritmetiske og logiske uttrykk, og presedensreglene som avgjør hva et uttrykk evaluerer til.

40 min
9 oppgaver
Variablerdatatyperuttrykkoperatorpresedens
Din fremgang i kapitlet
0 / 9 oppgaver
Kapitlets plass i kurset
Forkunnskaper: Dette kapitlet kan leses uten forkunnskaper — det er bokas første møte med Python, og alt forklares fra grunnen.

Har du aldri programmert før, finnes det to mykere innganger på plattformen som du kan bla gjennom først, uten at det er nødvendig:

- Programmering med Python — Python fra null, i et matematikkurs fra videregående.
- Programmering med Python — samme innføring, i en litt roligere versjon.

Er du usikker på om du er «god nok i matte» til IN1900: kapitlet her bruker ingen matematikk utover pluss, minus, gange og dele.

Løkke 1 — Verdier, navn og datatyper

En værstasjon på Blindern måler temperaturen hver time. Du vil regne på tallene: finne gjennomsnitt, sjekke om det frøs, telle antall målinger. Da må maskinen holde orden på to ting — verdiene (21.5, 4, «Blindern») og navnene du bruker på dem.

Et Python-program er lite mer enn en liste med slike navngivinger, og uttrykk som regner med dem. Vi begynner der, fordi kodesporing i bunn og grunn er å holde en slik navneliste i hodet.

Variabel og tilordning `=`

En variabel er et navn som peker på en verdi. Du lager den med et likhetstegn: navnet til venstre, verdien til høyre.

Likhetstegnet i Python betyr ikke «er lik» slik det gjør i matematikk. Det betyr «regn ut høyresiden, og la navnet på venstresiden peke på resultatet». Derfor er x = x + 1 en helt fornuftig setning: regn ut den gamle x pluss 1, og la x peke på det nye tallet.

temperatur = 21.5
temperatur = temperatur + 1
print(temperatur)

Utskrift:

22.5

`print(a, b, c)`

Skriver verdiene ut i terminalen og avslutter med linjeskift. Flere argumenter skilles av ett mellomrom — det er Python som setter det inn, ikke deg.

Dette er detaljen som avgjør flest kodesporingsoppgaver: print(3, 4) gir 3 4 med ett mellomrom, mens print('3' + '4') gir 34 uten.

print(3, 4)
print('sum:', 3 + 4)
print('3' + '4')

Utskrift:

3 4
sum: 7
34

Heltall (`int`)

Tall uten desimalpunkt: 4, -7, 1000. Heltall i Python har ingen øvre grense — 2**100 regnes ut eksakt, uten avrunding.

Så lenge du bare bruker +, -, * og ** på heltall, får du et heltall tilbake. Det er / som bryter mønsteret: den gir alltid et desimaltall, også når det går opp.

Flyttall (`float`)

Desimaltall: 21.5, -0.5, 1e-5 (som betyr 11051 \cdot 10^{-5}). Python skriver desimalskilletegnet som punktum, aldri komma — 21,5 er ikke ett tall i Python, men to.

Flyttall er tilnærminger. Maskinen lagrer dem i totallssystemet, og de fleste desimaltall får ikke plass eksakt. Derfor er 0.1 + 0.2 ikke helt lik 0.3:

print(0.1 + 0.2)
print(0.1 + 0.2 == 0.3)

Utskrift:

0.30000000000000004
False

Dette er ikke en feil i Python, det er slik flyttall virker overalt. Det er også grunnen til at testfunksjoner i kap. 3.1 sammenligner med en toleranse i stedet for med likhetstegn.

Sannhetsverdier (`bool`)

Datatypen med bare to verdier: True og False. Stor forbokstav, alltid — true finnes ikke i Python.

Sannhetsverdier oppstår normalt ikke fordi du skriver dem selv, men fordi du sammenligner noe: 5 > 3 er verdien True. De er også tall i forkledning: True oppfører seg som 1 og False som 0 i regnestykker, så True + True er 2.

Strenger (`str`)

Tekst, skrevet mellom enkle eller doble fnutter: 'Blindern' eller "Blindern". De to formene er likeverdige.

På strenger betyr + å skjøte sammen og * å gjenta: 'ab' + 'cd' gir 'abcd', og 'ab' * 2 gir 'abab'. Merk at '3' + '4' derfor gir '34' og ikke 7 — tallet 3 og tegnet '3' er to helt forskjellige verdier. Mer om strenger i kap. 1.4.

`type(x)`

Svarer med datatypen til verdien x. Utskriften ser slik ut: <class 'int'>.

Du bruker den nesten aldri i en eksamensbesvarelse, men den er uvurderlig når du selv skal sjekke om et uttrykk ga heltall eller desimaltall — nettopp det kodesporing spør om.

✏️Eksempel 1: Hvilken datatype fikk jeg?

En værstasjon lagrer fire opplysninger. Hvilken datatype har hver av dem, og hva skriver programmet ut?

Vi lar Python svare selv. Legg merke til at type skriver typenavnet inne i <class ...>:

temperatur = 21.5
antall_stasjoner = 4
navn = 'Blindern'
maalt_i_dag = True
print(type(temperatur))
print(type(antall_stasjoner))
print(type(navn))
print(type(maalt_i_dag))

Utskrift:

<class 'float'>
<class 'int'>
<class 'str'>
<class 'bool'>

Fire linjer inn, fire linjer ut: float, int, str, bool. Merk at det er verdien som bestemmer typen, ikke navnet — Python spør aldri hva du hadde tenkt.

📝Oppgave 1

(Innstegsoppgave — ren gjengivelse.) Skriv ned datatypen til hver av disse verdiene, med Pythons eget navn på typen:

a) -12

b) -12.0

c) '-12'

d) 12 > 3

Løkke 2 — De fire divisjonene

Nå kommer den mest lønnsomme halvtimen i kapitlet. Python har tre forskjellige måter å dele på, og de gir tre forskjellige svar på samme regnestykke. Nesten hvert midtveissett har minst ett spørsmål som lever av at studenten blander dem.

Divisjon `/`

Vanlig divisjon. Resultatet er alltid et flyttall, også når det går opp: 6 / 3 gir 2.0, ikke 2.

Det er verdt å merke seg i kodesporing: et desimalpunkt i utskriften avslører at det har vært en / inne i regnestykket.

Heltallsdivisjon `//`

Deler og runder resultatet nedover til nærmeste heltall. 7 // 2 gir 3.

«Nedover» betyr mot minus uendelig, ikke mot null. Derfor er -7 // 2 lik -4, ikke -3. Det er den fellen som går igjen. Får begge operandene være heltall, blir svaret et heltall; er én av dem et flyttall, blir svaret et flyttall med .0 (7.0 // 2 gir 3.0).

Modulo `%`

Resten etter heltallsdivisjon: 7 % 2 gir 1.

To bruksområder du får se om og om igjen: n % 2 == 0 betyr «n er et partall», og n % 5 == 0 betyr «n er delelig med 5». I Python har resten alltid samme fortegn som det du deler på, så -7 % 2 gir 1 (ikke -1). De to operatorene henger sammen: (a // b) * b + a % b gir alltid a tilbake.

✏️Eksempel 2: Tre måter å dele 7 på 2

Hva skriver dette programmet ut? Vær nøye med fortegnene.

Vi kjører det:

antall = 7
gruppestorrelse = 2
print(antall / gruppestorrelse)
print(antall // gruppestorrelse)
print(antall % gruppestorrelse)
print(-antall // gruppestorrelse, -antall % gruppestorrelse)

Utskrift:

3.5
3
1
-4 1

Linje for linje: / gir flyttallet 3.5. // kaster desimalene og gir 3 — sju personer fordelt to og to blir tre hele par. % gir 1 — én person står igjen.

Den siste linja er fellen. -7 // 2 er ikke -3. Runder du nedover fra 3,5-3{,}5, kommer du til 4-4. Og siden (-4) * 2 + 1 er -7, må resten være 1.

📝Oppgave 2

(Midtveisnivå, sjanger A — kodesporing.) Hva skriver programmet ut? Skriv utskriften nøyaktig, med linjeskift slik terminalen viser den.

maalinger = 13
kolonner = 4
print(maalinger // kolonner)
print(maalinger % kolonner)
print(maalinger / kolonner)

Potens `**`

Opphøyd i: 2 ** 3 gir 8. Med et negativt eksponentuttrykk får du flyttall: 2 ** -1 gir 0.5.

To særegenheter du må huske: ** binder sterkest av alle regneoperatorene, og den regnes ut fra høyre (den er høyre-assosiativ). Derfor er 2 ** 3 ** 2 det samme som 2(32)=29=5122^{(3^2)} = 2^9 = 512, ikke (23)2=64(2^3)^2 = 64. Og fordi ** binder sterkere enn minustegnet foran et tall, er -2 ** 2 lik -4.

✏️Eksempel 3: Potenser og fortegn

Fire uttrykk som ser nesten like ut. Hva skriver programmet ut?

print(2 ** 3 ** 2)
print((2 ** 3) ** 2)
print(-2 ** 2)
print((-2) ** 2)

Utskrift:

512
64
-4
4

Linje 1 og 2 skiller seg fordi ** regnes fra høyre: 232=29=5122^{3^2} = 2^9 = 512, mens parentesene i linje 2 tvinger (23)2=82=64(2^3)^2 = 8^2 = 64.

Linje 3 og 4 skiller seg fordi ** binder sterkere enn det unære minuset: i linje 3 regnes 2 ** 2 først og fortegnet snus etterpå, mens parentesen i linje 4 gjør at hele 2-2 opphøyes.

Praktisk regel i besvarelsen: er du i tvil, sett parentes. Sensor trekker aldri for en parentes du ikke trengte.

📝Oppgave 3

(Midtveisnivå, sjanger A.) Hva skriver programmet ut?

a = 3
print(2 ** a ** 2)
print(-a ** 2 + 1)
print(2 ** -2)

Løkke 3 — Presedens: hva regnes ut først?

Et uttrykk som 6 + 4 * 2 har bare ett riktig svar, og Python bruker samme regler du lærte på skolen — pluss noen flere, fordi Python har flere operatorer enn matematikken.

Operatorpresedens

Rekkefølgen Python regner ut i, fra det som bindes sterkest til det som bindes svakest:

1. () — parentes
2. ** — potens (regnes fra høyre)
3. -x — unært minus
4. *, /, //, % — regnes fra venstre mot høyre
5. +, - — regnes fra venstre mot høyre
6. <, <=, >, >=, ==, != — sammenligninger
7. not
8. and
9. or

To operatorer på samme nivå tas fra venstre: 12 / 3 * 2 er (12 / 3) * 2 som gir 8.0, ikke 12 / 6. Eneste unntak er **, som tas fra høyre.

Merk at alle regneoperatorene kommer før sammenligningene, og at not kommer før and, som kommer før or.

✏️Eksempel 4: Fem uttrykk med samme tall

Tallene 6 og 4 i fem forskjellige uttrykk. Hva skriver programmet ut?

a = 6
b = 4
print(a + b * 2)
print((a + b) * 2)
print(a / b * 2)
print(a - b - 1)
print(a % b * 2)

Utskrift:

14
20
3.0
1
4

- 6 + 4 * 2: gangetegnet først, altså 6 + 8.
- (6 + 4) * 2: parentesen først, altså 10 * 2.
- 6 / 4 * 2: samme nivå, fra venstre: 1.5 * 2. Flyttall, fordi / var inne.
- 6 - 4 - 1: fra venstre: 2 - 1. Hadde det vært fra høyre, ville svaret vært 3.
- 6 % 4 * 2: % og * er samme nivå, fra venstre: 2 * 2.

Den tredje og den femte linja er de som skiller. Begge lever av regelen «samme nivå tas fra venstre».

📝Oppgave 4

(Midtveisnivå, sjanger A.) Hva skriver programmet ut?

x = 10
y = 3
print(x - y * 2 + 1)
print(x // y ** 2)
print(x / y // 2)

Løkke 4 — Logiske uttrykk

En værstasjon skal varsle om frost. Det er et spørsmål med to svar, og slike spørsmål skriver du i Python som logiske uttrykk. De er kjernen i alle if-setninger og while-løkker senere i boka, og de utgjør en egen matche-tabell på eksamen (sjanger D).

Sammenligningsoperatorer og kjeding
<, <=, >, >= sammenligner størrelse; == spør om likhet og != om ulikhet. Hver av dem gir True eller False.

To fallgruver. Ett likhetstegn tilordner, to sammenligner — x = 5 og x == 5 er to helt ulike setninger. Og Python tillater kjeding: 0 < x < 10 er lovlig og betyr 0 < x and x < 10. Det er praktisk, men også en yndet felle, fordi den samme skrivemåten ikke betyr noe fornuftig i mange andre språk.

`and`, `or`, `not`
a and b er sann bare når begge er sanne. a or b er sann når minst én er sann. not a snur svaret.

Rekkefølgen er not før and før or. Derfor betyr not x > 3 or x == 5 det samme som (not (x > 3)) or (x == 5): not-et gjelder bare den første sammenligningen, ikke hele uttrykket. Er du i tvil, sett parentes.

Python er dessuten lat: i a and b regnes b bare ut hvis a var sann. Det er derfor n != 0 and 10 / n > 1 er trygt selv når n er null.

Sannhetsverdi av en verdi (`bool(x)`)

Alle verdier kan brukes der Python venter et ja/nei-svar. Regelen er kort: tallet 0, den tomme strengen '', den tomme lista [] og den tomme ordboka {} regnes som falske. Alt annet er sant.

bool(x) viser hva Python mener om x. Dette forklarer hvorfor if verdier: er et vanlig og idiomatisk uttrykk for «hvis lista ikke er tom».

✏️Eksempel 5: Sanne og falske uttrykk

Temperaturen er målt til 5 grader. Hva skriver programmet ut?

t = 5
print(0 < t < 10)
print(t > 3 and t % 2 == 0)
print(not t > 3 or t == 5)
print(bool(0), bool(''), bool(-1))

Utskrift:

True
False
True
False False True

- 0 < 5 < 10: begge leddene i kjeden er sanne.
- 5 > 3 and 5 % 2 == 0: første ledd sant, andre ledd falskt (5 er ikke et partall), og and krever begge.
- not 5 > 3 or 5 == 5: not-et tar bare 5 > 3, som er sant, så første ledd blir False. Andre ledd er sant, og or krever bare ett.
- bool(0), bool('') er falske; bool(-1) er sann, for det er bare null som er falsk, ikke negative tall.

Legg merke til den siste: mange gjetter False for bool(-1) fordi negativt «føles» som nei.

📝Oppgave 5

(Midtveisnivå, sjanger D — matche-tabell der du avgjør sannhetsverdien til hvert uttrykk.) La n = 12 og m = 5. Avgjør for hvert uttrykk om det er True eller False.

| Uttrykk |
|---|
| n % m == 2 |
| n > m and m > 10 |
| not n == 12 |
| m < n < 20 |
| n % 2 == 0 or m % 2 == 0 |

Løkke 5 — Konvertering, avrunding og korte tilordninger

Til slutt tre småting som dukker opp i nesten hver eneste kodesporingsoppgave: å bytte datatype, å runde av, og den korte skrivemåten for «legg til».

`int(x)`

Gjør x om til et heltall. På et flyttall kutter den desimalene bort — den runder ikke. Og den kutter mot null: int(2.7) gir 2, og int(-2.7) gir -2.

Det er en viktig forskjell fra //, som runder nedover: int(-2.7) er -2, mens -27 // 10 er -3. På en streng virker int bare hvis strengen inneholder et helt tall: int('42') gir 42, mens int('42.0') og int('to') stopper programmet med en feilmelding.

`float(x)`

Gjør x om til et flyttall: float(3) gir 3.0, og float('2.5') gir 2.5.

Dette er konverteringen du bruker når du har lest tall fra fil eller fra kommandolinjen — der kommer alt inn som tekst, og tekst kan man ikke regne med. Se kap. 2.1.

`round(x)` og `round(x, n)`
round(x) runder av til nærmeste heltall og gir et heltall. round(x, n) runder av til n desimaler og gir et flyttall.

Særegenhet du bør kjenne: står tallet midt imellom, runder Python til det nærmeste partallet. Derfor er round(0.5) lik 0, round(1.5) lik 2 og round(2.5) lik 2. Regelen kalles bankers avrunding, og den finnes for at mange avrundinger ikke skal skjeve seg systematisk oppover.

Augmenterte tilordninger (`+=`, `-=`, `*=`, `//=`)
s += x er kortformen for s = s + x, og tilsvarende for de andre. Kortformen er den idiomatiske måten å bygge opp en sum eller en teller.

Du får se den i hver rekke-oppgave i kap. 3.2, som s += ledd. Merk at variabelen må ha en verdi først: s += 1 på et navn som ikke finnes, stopper programmet.

✏️Eksempel 6: Konvertering og avrunding i samme sporing

Dette er en typisk midtveisoppgave: fem linjer, ingen løkker, men fire ulike feller. Hva skriver programmet ut?

x = 2.7
print(int(x), int(-x))
print(round(x), round(-x))
print(round(0.5), round(1.5), round(2.5))
t = 10
t += 5
t //= 4
print(t)

Utskrift:

2 -2
3 -3
0 2 2
3

Sporingstavle

LinjeHva skjertUtskrift
2int kutter mot null i begge retninger2 -2
3round runder normalt3 -3
4midt imellom: rund til partall0 2 2
5–7t blir 10, så 15, så 15 // 4 som er 333

De to linjene som skiller besvarelsene er linje 2 og linje 4. int(-2.7) er -2 fordi int kutter, og round(2.5) er 2 fordi Python runder til nærmeste partall når det står midt imellom.
📝Oppgave 6

(Midtveisnivå, sjanger A.) Hva skriver programmet ut?

verdi = -3.6
print(int(verdi))
print(round(verdi))
print(round(verdi, 1))
s = 7
s *= 3
s %= 4
print(s)

📝Oppgave 7

(Midtveisnivå, sjanger A — kodesporing med blandede datatyper.) Hva skriver programmet ut?

antall = 4
sum_grader = 82.0
print(sum_grader / antall)
print(sum_grader // antall)
print(antall * 2 ** 2)
print(antall == 4.0)

📝Oppgave 8
Eksamensnivå, sjanger A

Hva skriver programmet ut?

n = -13
d = 4
print(n // d, n % d)
print(-(n // d), int(n / d))
print(n // d * d + n % d)

📝Oppgave 9
Eksamensnivå, sjanger D

La x = 0, tekst = 'null' og verdier = [] (en tom liste).

Avgjør for hvert uttrykk om det er True eller False.

a) bool(x)

b) bool(tekst)

c) bool(verdier)

d) x == 0 and not verdier

e) x or tekst

f) not x and not tekst

API- og konstruksjonsliste

Begrepsbank

Begrepsbanken er flashcard-/repetisjonsstoff — den gjentar det du nettopp har lest. Hopp trygt over ved førstegangslesing; tidsanslaget for kapitlet gjelder kjernestoffet.

`abs(x)`

Tallverdien til x, uten fortegn: abs(-4.5) gir 4.5, og abs(3) gir 3.

Den er viktigere enn den ser ut: hver testfunksjon i boka bruker abs(forventet - beregnet) < tol for å sjekke om to flyttall er «nær nok». Se kap. 3.1.

Dynamisk typing

I Python bestemmes datatypen av verdien, ikke av navnet, og et navn kan peke på ulike typer etter hverandre: x = 4 og deretter x = 'fire' er lovlig.

Konsekvensen for deg er at typefeil ikke oppdages før koden kjører. Skriver du '3' + 4, får du ingen advarsel på forhånd — programmet stopper når linja nås, med en TypeError. Det er en av exception-typene i kap. 2.2.

Uttrykk og setning

Et uttrykk har en verdi: 2 + 2, x > 3, int('42'). En setning gjør noe: x = 5, print(x).

Skillet er praktisk i sporing: hvert uttrykk kan du erstatte med verdien sin og gå videre. Det er nettopp det en sporingstavle gjør, linje for linje.

Flyttall er tilnærminger

Et flyttall lagres med et endelig antall binære siffer, så de fleste desimaltall blir litt feil i siste siffer. Derfor er 0.1 + 0.2 lik 0.30000000000000004, og 1 / 3 skrives 0.3333333333333333.

Tre konsekvenser du får bruk for: (1) sammenlign aldri flyttall med ==, bruk en toleranse; (2) bruk formatert utskrift når du vil vise et pent tall, se kap. 1.4; (3) heltall har ikke dette problemet — de er eksakte, uansett størrelse.

Repetisjon — de fem 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.