Nøstede forgreininger

I artikkelen om å strukturere if har vi følgende kode for å lese inn vekt og beregne porto på brev:

# Leser inn vekt og beregner porto
vekt = int(input("Oppgi vekt i gram: "))
if vekt < 20:
    porto = 23
elif vekt < 50:
    porto = 29
elif vekt < 100:
    porto = 36
elif vekt < 350:
    porto = 55
elif vekt < 1000:
    porto = 90
else:
    porto = 125
print(f"Porto på et brev på {vekt} g er kr {porto},-")

Vi forutsetter der imidlertid at vi ikke skriver inn en ulovlig vekt, det vil si en vekt som er mindre eller lik 0 eller større eller lik 2000, som er største tillatte vekt på brev. Skriver vi inn 0 eller mindre, blir porto satt til 23. fordi betingelsen vekt < 20 da er sann. Skriver vi inn 2000 eller mer, blir porto satt til 125, fordi dette tilfellet fanges opp av else.

For å forbedre koden skal vi legge inn en kontroll på at vekten er lovlig, og skrive en feilmelding hvis ikke. Vi forsøker først å legge til en ekstra betingelse i if-strukturen, slik det er vist i eksempel 1.

Eksempel 1:

# Leser inn vekt og beregner porto
vekt = int(input("Oppgi vekt i gram: "))
if vekt <= 0 or vekt >= 2000:  # Feilkontroll
    print("Vekta må være større enn 0 og mindre enn 2000 g.")
elif vekt < 20:
    porto = 23
elif vekt < 50:
    porto = 29
elif vekt < 100:
    porto = 36
elif vekt < 350:
    porto = 55
elif vekt < 1000:
    porto = 90
else:
    porto = 125
print(f"Porto på et brev på {vekt} g er kr {porto},-")

I eksempel 1 vil imidlertid print() alltid bli utført fordi linja med print() står etter if-strukturen. Hvis vi har lest inn en ulovlig verdi, vil vi da få en feilmelding fordi variabelen porto ikke eksisterer, siden porto bare blir gitt verdi når vi har en lovlig vekt. En alternativ løsning er å fjerne den generelle print() etter if-strukturen, og i stedet legge inn varianter i alle betingelsene, slik det er gjort i eksempel 2.

Eksempel 2:

# Leser inn vekt og beregner porto
vekt = int(input("Oppgi vekt i gram: "))
if vekt <= 0 or vekt >= 2000:  # Feilkontroll
    print("Vekta må være større enn 0 og mindre enn 2000 g.")
elif vekt < 20:
    print(f"Porto på et brev på {vekt} g er kr 23,-")
elif vekt < 50:
    print(f"Porto på et brev på {vekt} g er kr 29,-")
elif vekt < 100:
    print(f"Porto på et brev på {vekt} g er kr 36,-")
elif vekt < 350:
    print(f"Porto på et brev på {vekt} g er kr 55,-")
elif vekt < 1000:
    print(f"Porto på et brev på {vekt} g er kr 90,-")
else:
    print(f"Porto på et brev på {vekt} g er kr 125,-")

Koden i eksempel 2 vil fungere, men er et eksempel på svært dårlig design. Alle gjentakelsene av print() gjør koden uoversiktlig og vanskelig å vedlikeholde. Hvis vi for eksempel vil endre «g» med «gram» i utskriften, må vi redigere 6 plasser.

En bedre løsning vil være å legge feilkontrollen i en egen if-struktur, slik det er vist i eksempel 3.

Eksempel 3:

# Leser inn vekt og beregner porto
vekt = int(input("Oppgi vekt i gram: "))
if vekt <= 0 or vekt >= 2000:  # Feilkontroll
    print("Vekta må være større enn 0 og mindre enn 2000 g.")
else:
    if vekt < 20:
        porto = 23
    elif vekt < 50:
        porto = 29
    elif vekt < 100:
        porto = 36
    elif vekt < 350:
        porto = 55
    elif vekt < 1000:
        porto = 90
    else:
        porto = 125
    print(f"Porto på et brev på {vekt} g er kr {porto},-")

I eksempel 3 har vi en if-struktur inni en annen if-struktur, noe vi kaller en nøstet if-struktur. I den ytre if-strukturen sjekker vi først om vekta er lovlig, og skriver ut feilmelding hvis ikke. Og bare hvis vekta er lovlig, kommer vi til den indre if-strukturen der vi beregner og skriver ut porto.

Logisk sett er feilsjekk og prisberegning to helt forskjellige ting, så det er god design å skille de to fra hverandre med hver sin if-struktur. Vi ser at innrykk hjelper oss å holde rede på hva som hører til i hvilken if-struktur.

Oppgave 1:

En elektronikkbutikk selger lysdioder til en stykkpris på kr 3,50. Men kjøper vi 10 eller mer, er stykkprisen kr 3,00, og kjøper vi 100 eller mer, er stykkprisen kr 2,50. Python-koden under spør etter hvor mange lysdioder vi vil kjøpe, og beregner og skriver ut både stykkpris og total pris, basert på dette.

# Leser inn antall lysdioder, og skriver ut stykkpris og totalpris
antall = int(input("Hvor mange lysdioder vil du kjøpe? "))
if antall < 10:
    stykkpris = 3.50
elif antall < 100:
    stykkpris = 3.00
else:
    stykkpris = 2.50
print(f"{antall} lysdioder à kr {stykkpris:.02f}, totalt kr {antall*stykkpris:.02f}.")
      1. Utvid koden med en ytre if som sjekker at antall kjøpte dioder er større enn 0, og skriver ut en feilmelding hvis ikke.
         
      2. Utvid ytre if slik at den også sjekker om antall kjøpte dioder er 1000 eller mer. I så fall skal det skrives ut en melding om at kjøperen skal kontakte kundeservice for et tilbud.

I disse spesialtilfellene skal det ikke gjøres noen beregning eller utskrift av pris.

Se løsningsforslag

Både i ytre og indre if kan vi ha elif og else, slik som eksempel 4 er et stilisert eksempel på. Det er innrykkene som viser hvilke if, elif og else som henger sammen, slik det er markert med piler.

Eksempel 4:

Stilisert eksempel på nøstet if

Det er ingen teoretisk grense for hvor mange if vi kan ha inni hverandre, men i praksis blir det sjelden bruk for mer enn to-tre. Det er også mulig å ha if inni løkker, og vice versa. Det blir det ofte bruk for i praksis.

 

Kilder

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