5. Selektion (if ... elif ... else ...)

Det er ofte nødvendigt at vælge (selektere) mellem forskellige stykker kode som skal udføres i forskellige situationer.

Tag for eksempel følgende simple program som tegner et polygon vha. turtle-modulet:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
import turtle
t = turtle.Turtle()

n = int(input("How many sides would you like in your polygon?"))

for i in range(n):
    t.forward(100)
    t.right(360/n)

turtle.exitonclick()

Programmet spørger brugeren hvor mange sider der skal være i polygonet, men programmet opfører sig meningsløst hvis brugeren vælger et n som er mindre end 3 (et polygon kan f.eks. ikke have 1 eller -2 sider).

Vi har brug for en konstruktion som kan vælge (selektere) mellem forskellige stykker kode baseret på værdien af n. Hvis n er mindre end 3 skal brugeren modtage en fejlmeddelse ellers skal polygonet tegnet vha. for-loopet. Dette gøres vha. en såkaldt if ... elif ... else konstruktion:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
import turtle
t = turtle.Turtle()

n = int(input("How many sides to draw in polygon?"))

if n < 3:
    print("Error, the polygon should have at least 3 sides")
else:
    for i in range(n):
        t.forward(100)
        t.right(360/n)

        turtle.exitonclick()

Linje 6 tester om n er mindre end 3 og hvis n er mindre end 3 udføres linje 7. Hvis testen i linje 6 afgører at n ikke er mindre end 3 så udføres koden som står under under linje 8 (linje 9-13). n < 3 fra linje 6 kaldes en sammenligning eller et boolsk udtryk.

Generelt har if ... elif ... else konstruktioner følgende udseende:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
expr1

if A:
    expr2
elif B:
    expr3
else:
    expr4

expr5

A og B i linje 3 og 5 er boolske udtryk som enten er sande (True) eller falske (False), f.eks. n<3.

expr1, expr2 osv. er generelle python udtryk eller kommandoer, f.eks. print("whatever") eller a = 2.

Hvis A er sand udføres expr2. Hvis A er falsk testes det om B er sand. Hvis B er sand udføres expr3. Hvis B også er falsk udføres expr4.

expr1 udføres altid i starten af programmet og expr5 udføres altid til sidst. Programmet kan beskrives vha. nedenstående flowdiagram. Flowdiagrammet understreger hvad der lige er blevet sagt, nemlig at kun én af expr1, expr2 og expr3 udføres.

../_images/if-elif-else-flow.png

Et konkret eksempel på flowdiagrammet kunne være:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
d = input("How many days in a year?")

if d == "365":
    print("Correct!")
elif d == "366":
    print("Correct, for a leap year!")
else:
    print("Wrong ...")

print("Thanks for playing.")

Opgave

Hvilke Python udtryk eller kommandoer fra ovenstående eksempler svarer til expr1, expr2 osv. fra flowdiagrammet?

Der kan være et valgfrit antal elif cases.

Opgave

Skriv et program som spørger brugeren hvor mange dage der er i en måned og vurderer svaret vha. if ... elif ... else med mindst 2 elif-cases.

if ... elif ... else udtryk også nestes, i.e. expr1 fra tidligere eksempel kan være et andet if ... elif ... else udtryk.

1
2
3
4
5
6
7
8
9
month = input("Name a month (jan, feb, apr etc.): ")
num_days = input("How many days in {}?".format(month))

if month in ['jan', 'mar', 'may', 'jul', 'aug', 'oct', 'dec']:
    if num_days == "31":
        print("Correct!")

    else:
        print("Wrong!")

month in ['jan', 'mar', 'may'] fra linje 4 er endnu et boolsk udtryk, som afgører om tekststrengen indeholdet i variablen month findes blandt tekststrengene i listen ['jan', 'mar', 'may']. Svaret på spørgsmålet er True eller False.

Opgave

Udvid ovenstående eksempel således det også kan håndtere februar (husk februar kan have 29 dage).

Udvid det yderligere så det kan håndtere månederne med 30 dage.

De to nestede if-udtryk fra eksemplet med måneder og deres dage kan omskrives til et enkelt if ... else-udtryk med de to betingelser (at måneden findes i en liste og at antal dage er 31) kombineret til en enkelt betingelse:

1
2
3
4
5
6
7
month = input("Name a month (jan, feb, apr etc.): ")
num_days = input("How many days in {}?".format(month))

if month in ['jan', 'mar', 'may', 'jul', 'aug', 'oct', 'dec'] and num_days == "31":
    print("Correct!")
else:
    print("Wrong!")

and i linje 4 er en såkaldt boolsk operator eller logisk operator. Den bruges til at sammensætte to boolske udtryk og giver svaret True hvis de to boolske udtryk (month in ['jan' og num_days == "31") begge er sande, ellers giver den False.

Der findes en tilsvarende boolsk operator or som også sammensætter to boolske udtryk, men den svarer True hvis blot ét af de to boolske udtryk er sande. or giver kun False hvis begge boolske udtryk er falske.

Opgave

Modificer din forrige opgave, eller udvid ovenstående eksempel, således du benytter and ved månederne med 30 dage og or i forbindelse med specialtilfældet februar.

5.1. Sammenligninger og andre boolske udtryk

a == b bruges til at tjekke om værdien af a og b er ens.

a != b bruges til at tjekke om værdien af a og b er forskellig.

a > b bruges til at tjekke om værdien af a er større end værdien af b.

a >= b bruges til at tjekke om værdien af a er større end eller lig med værdien af b.

a < b bruges til at tjekke om værdien af a er mindre end værdien af b.

a <= b bruges til at tjekke om værdien af a er mindre end eller lig med værdien af b.

a in [b,c,d,e] bruges til at afgøre om værdien af a findes blandt værdierne i listen.

"ab" in "abcdef" bruges til at afgøre om tekstrengen "ab" findes i tekststrengen "abcdef".

Opgave

Afgør manuelt om følgende udsagn er sande eller falske, og test det efterfølgende (måske et ad gangen) i en python-fil ala:

1
2
#print(2 == 2)
print(2 > 3)

3 < 2

3 != 2

5 == 5

"what" == "ever"

"abc" == "abc"

2*3-2 == 4

int(2.7) == 2

min([1,2,3]) > 0

4>=4

4 in [3,6,1,8]

"ab" in ["aa", "ab", "ac", "ad"]

"name" in "Hello, my name is Alice"

"alice" in "Hello, my name is Alice"

5 > 2 and 8 > 5

7 > 2 and 7 > 7

2 == 3 or 2>0

"lol" == "LOL" or "lol" == "lol"

Opgave

1
n = int(input("Write a number between 1 and 100:"))

Udvid programmet således det viser brugeren en fejl hvis brugeren indtaster et tal som ikke ligger mellem 0 og 100.

Lav en løsning som bruger nestede``if ... else``-udtryk og en anden løsning som bruger and.

Hvis du har brugt <= og >= så lav din løsning om således den bruger < og > i stedet for, og vice versa.

Opgave

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
import random

num = random.randint(1,10)
print("I've picked a number between 1 and 10, "
      "guess what it is!")

while True:
    guess = int(input("Guess: "))

    if guess == num:
        print("Yeah, you win!")
        break

Udvid ovenstående program således det giver brugeren/spilleren et hint til om han/hun skal gætte højere eller lavere.