Forgreininger med «if»

if

I programmeringsspråk er vi avhengige av å ha kontrollstrukturer som definerer hvilken rekkefølge kodelinjer skal kjøres i. Den grunnleggende struktuen er sekvens, som betyr at kodelinjene kjøres én for én fra toppen og nedover. Nå skal vi se på kontrollstrukturen seleksjon, der vi kan gjøre forgreininger og velge forskjellige veier gjennom koden avhengig av gitte betingelser.

Den enkleste forgreiningen består i å hoppe forbi én eller flere linjer.

Som eksempel ser vi på Python-kode som leser inn radius til en sirkel, og så beregner og skriver ut sirkelens omkrets, etterfulgt av hilsenen Ha en fin dag.

# Les inn radius til en sirkel og skriv ut omkretsen
radius = int(input("Oppgi radius: "))
omkrets = 2 * 3.14 * radius
print(f"En sirkel med radius {radius} har omkrets ca. {omkrets}.")
print("Ha en fin dag!")

Når vi kjører koden, spør Python etter radius. Hvis vi da for eksempel svarer 1, skriver Python
En sirkel med radius 1 har omkrets ca. 6.28.
Ha en fin dag!

Men hvis vi svarer -1, skriver Python
En sirkel med radius -1 har omkrets ca. -6.28.
Ha en fin dag!

Dette er jo meningsløst, for vi kan ikke ha en sirkel med negativ radius. Vi ønsker derfor å gjøre en forgreining forbi beregning og utskrift av omkrets hvis radius ikke er større eller lik 0. Til det bruker vi en if-struktur:

# Les inn radius til en sirkel og skriv ut omkretsen
# Radius må være større eller lik 0
radius = int(input("Oppgi radius: "))
if radius >= 0:
    omkrets = 2 * 3.14 * radius
    print(f"En sirkel med radius {radius} har omkrets ca. {omkrets}.")
print("Ha en fin dag!")

Her bruker vi sammenlikningsoperatoren større-eller-lik, som består av et større-enn tegn og et likhetstegn satt sammen, slik det står i artikkelen om sammenlikningsoperatorer.

En if-struktur består av kodeordet if etterfulgt av en betingelse, og så et kolon. Deretter kommer én eller flere linjer som er rykket inn. Hvis betingelsen er sann, vil koden i de innrykkede linjene bli kjørt. I eksemplet over er betingelsen at verdien til variabelen radius er større eller lik 0.

I stedet for å si «én eller flere linjer», vil vi referere til kodelinjer som hører sammen, som en kodeblokk, eller bare blokk.

Det er altså innrykket som avgjør hva som hører til kodeblokka i if-strukturen. Linja print("Ha en fin dag!") er ikke rykket inn, så den hører ikke til blokka. Teksten Ha en fin dag! vil derfor bli skrevet ut uavhengig av verdien til radius.

Python stiller i seg selv ikke noe krav til hvor stort et innrykk skal være, men stilguiden PEP 8 anbefaler å rykke inn med 4 blanke tegn. I Thonny bruker vi tabulatortasten til å sette innrykk. Når vi avslutter ei linje med kolon, rykker Thonny inn neste linje automatisk.

ifelse

En ulempe med eksempelet vårt er at hvis betingelsen ikke er sann, altså at radius ikke er større eller lik 0, skjer det ingenting. Dette er dårlig design, et prinsipp for god design er at kode alltid skal gi en form for respons. Vi bygger derfor inn utskrift av en feilmelding. Denne skal bare komme hvis radius er mindre enn 0, så vi legger inn en if-struktur til:

# Les inn radius til en sirkel og skriv ut omkretsen
# Radius må være større eller lik 0
radius = int(input("Oppgi radius: "))
if radius >= 0:
    omkrets = 2 * 3.14 * radius
    print(f"En sirkel med radius {radius} har omkrets ca. {omkrets}.")
if radius < 0:
    # Skriv feilmelding
    print("Radius kan ikke være negativ.")
print("Ha en fin dag!")

Men dette er klønete, for her sjekker vi verdien til radius to ganger. Først undersøker vi om radius er større eller lik 0, deretter om radius er mindre enn 0. Og den siste sjekken er overflødig, for hvis radius ikke er større eller lik 0, så må jo radius være mindre enn 0. I slike tilfeller bruker vi derfor ikke to if-strukturer, men én if-struktur med else:

# Les inn radius til en sirkel og skriv ut omkretsen
# Radius må være større eller lik 0
radius = int(input("Oppgi radius: "))
if radius >= 0:
    omkrets = 2 * 3.14 * radius
    print(f"En sirkel med radius {radius} har omkrets ca. {omkrets}.")
else:
    # Skriv feilmelding
    print("Radius kan ikke være negativ.")
print("Ha en fin dag!")

Dersom if-betingelsen er sann, kjøres den etterfølgende kodeblokka, mens blokka bak else blir hoppet over. Dersom if-betingelsen ikke er sann, blir den etterfølgende kodeblokka hoppet over, mens blokka bak else blir kjørt. Uansett blir én og bare én av kodeblokkene kjørt.

Oppgave 1:

Et krydder som selges i løsvekt, koster kr 0,90 per gram hvis vi kjøper inntil 25 gram og kr 0,80 per gram hvis vi kjøper 25 gram eller mer. Skriv Python-kode som leser inn vekt og beregner og skriver ut gramprisen.

Se løsningsforslag

ifelifelse

La oss så si at vi ønsker å skrive ut en egen melding hvis radius er akkurat 0, noe sånt som Når radius er 0, er omkretsen 0. Da har vi tre valg, radius større enn 0, radius lik 0 og radius mindre enn 0, og det kan vi ikke håndtere med ifelse. I stedet utvider vi til ifelifelse, som lar oss ha flere valg. Vi kan gjøre det slik:

# Les inn radius til en sirkel og skriv ut omkretsen
# Radius må være større eller lik 0
radius = int(input("Oppgi radius: "))
if radius > 0:
    omkrets = 2 * 3.14 * radius
    print(f"En sirkel med radius {radius} har omkrets ca. {omkrets}.")
elif radius == 0:
    print("Når radius er 0, er omkretsen 0")
else:
    # Skriv feilmelding
    print("Radius kan ikke være negativ.")
print("Ha en fin dag!")

For å sjekke om radius er 0 bruker vi sammenlikningsoperatoren er-lik, som består to likhetstegn satt sammen, slik det står i artikkelen om sammenlikningsoperatorer.

Kodeordet elif er en sammentrekning av «else if». elif etterfølges på samme måte som if av en betingelse og et kolon, og så kommer en innrykket kodeblokk.

Eventuelle elif kommer rett etter if. Etter elif kan vi ha else, men vi trenger ikke ha else. Vi kan altså ha fire varianter:

if
ifelse
ifelif
ifelifelse

Vi kan ha så mange elif vi vil etter hverandre, alle med sin egen betingelse.

pass

En kodeblokk i Python må bestå av minst én linje. Har vi en if, må det altså følge minst én innrykket linje etterpå. Men det kan hende at vi under arbeid med å utvikle kode er kommet så langt at vi har betingelsene i en if-struktur ferdig, men ikke det som skal stå i kodeblokkene. Da kan vi sette inn kodeordet pass, som ikke gjør noe som helst, men bare tjener som en plassholder. Hvis vi for eksempel leser inn radius og skal gjøre forskjellige ting avhengig av om radius er større enn 0, lik 0, eller mindre enn 0, men ikke har bestemt hva enda, kan vi bruke dette kodeskjelettet:

# Les inn radius til en sirkel og gjør noe
# Radius må være større eller lik 0
radius = int(input("Oppgi radius: "))
if radius > 0:
    pass
elif radius == 0:
    pass
else:
    pass

Denne koden leser inn radius og sjekker verdien, men gjør ikke mer.

pass skal imidlertid bare brukes som et hjelpemiddel mens vi utvikler kode. Har vi pass i ferdig kode, har vi sannsynligvis ikke strukturert koden optimalt.

Oppgave 2:

En student har skrevet koden under for å doble verdien til variabelen x hvis x er større enn 0, men la x være uendret ellers:

if x > 0:
    x *= 2
else:
    x = x

En annen student har skrevet koden under for å gjøre det samme:

if x > 0:
    x *= 2
else:
    pass

Vurder om én av de to variantene er bedre enn den andre, og om koden eventuelt kan skrives på en enklere måte.

Se løsningsforslag

Oppgave 3:

I koden under har vi brukt en innrykket kommentar i stedet for pass. Vurder om koden er riktig.

radius = int(input("Oppgi radius: "))
if radius >= 0:
    # Kommer senere
else:
    print("Radius kan ikke være negativ.")

Se løsningsforslag

SkjermfilmSe film om forgreinger med if

Kilder

    • Matthes A. (2019). Python Crash Course. no starch press

Bruk av innrykk for å angi hva som hører til en kodeblokk, er karakteristisk for Python. I språk som C og JavaScript brukes krøllparenteser, { }, for å avgrense kodeblokker, men samtidig anbefales det å bruke innrykk for lesbarhetens skyld. Python har like godt gjort innrykket obligatorisk og droppet parentesene.

I programmeringsspråk som C og JavaScript kreves det at betingelsen i en if-struktur skal stå i parentes. En slik parentes har ingen effekt, og i Python er den like godt droppet.

I programmeringsspråk som C og JavaScript kan vi lage kodeblokker uten innhold ved å bruke krøllparenteser uten noe mellom, og det er derfor ikke bruk for noe eget pass-kodeord.