Konsten att välja

Fler än två vägar

I Vägskälet introducerade vi if och else, ett villkor, två möjliga vägar. Det räckte för textäventyret. Men de flesta beslut har fler än två utgångar. Ett tal är positivt, negativt eller noll. Ett betyg är A, B, C eller underkänt. Tre utfall kräver två beslutsrutor i flödesschemat, och ett enkelt if/else täcker bara den första. Sätter du ett nytt if direkt efter det första löser du det tekniskt, men du skapar ett subtilt logikfel som Python aldrig berättar om. Det finns ett bättre sätt: elif.

En sak till följer med hela vägen: indraget. Du vet redan att de fyra mellanslagen avgör vad som tillhör ett block. I en elif-kedja blir de allvar, för nu är det indraget som avgör vilken gren en rad hamnar i.

elif, den saknade grenen

I pseudokoden från Kartan ritas behövde du två romber för att hantera tre utfall. elif Förkortning av else if. Kedjekopplar ett nytt villkor till föregående if, kontrolleras bara om alla föregående villkor i kedjan var falska. Gör grenar exklusiva: bara ett block per kedja kan köras. Se: Konsten att välja , else if är Pythons sätt att kedjekoppla de romberna utan att bygga nästlade strukturer:

Exemplet nedan använder >=, större än eller lika med. Behöver du fräscha upp de sex jämförelseoperatorerna finns hela tabellen i Vägskälet.

Editor

Redo.

Python utvärderar villkoren uppifrån och ned. Så fort ett villkor är sant körs det blocket, och resten av kedjan hoppas över helt. Med poäng = 85 stämmer inte >= 90, men >= 70 stämmer, Python skriver ut "Betyg: B" och läser aldrig de efterföljande elif-raderna.

Ändra poäng och kör igen tills du fått fram alla fyra utskrifterna. Prova sedan exakt 90: vilken gren vinner, och vad säger det om skillnaden mellan >= och >?

Att kedjan stannar vid första träffen är också det som gör ordningen till en del av logiken. Flytta upp poäng >= 50 överst och kör med 95. Alla godkända får plötsligt C, för 95 >= 50 är sant och Python läser aldrig vidare. Den strängaste gränsen måste stå först.

Skillnaden mellan elif och ett nytt if

Det vanligaste logikfelet med grenar är att byta ut elif mot ett nytt if utan att inse konsekvensen. Koden ser nästan likadan ut. Python klagar inte, men resultatet kan vara helt fel. Testa:

Editor

Redo.

Kör koden som den står: en rad skrivs ut, Betyg: A. Byt nu ut elif mot ett nytt if och kör igen. Plötsligt får du både Betyg: A och Betyg: B, för 95 uppfyller båda villkoren och två fristående if kontrolleras oberoende av varandra. elif hoppar över resten av kedjan så fort ett villkor stämt. Skillnaden syns inte i koden, den syns först när du kör. Vill du se valet ske, lägg en brytpunkt före if-satsen och stega med F10, då pekar debuggern ut exakt vilken gren Python tar.

När indraget går fel

Du har skrivit indenterade block sedan Vägskälet. Det som inte hänt än är att du sett vad som händer när Indrag Fyra mellanslag i början av en rad som talar om för Python att raden tillhör ett kodblock. Obligatoriskt, fel indrag ger IndentationError. Se: Vägskälet är fel, och det är värt att framkalla med flit. I språk som JavaScript, Java och C hålls block ihop av {}, och indraget är bara läsbarhet. Python har inga klamrar, så indraget bär hela informationen ensamt.

Editor

Redo.

Kör koden. De två indenterade raderna tillhör if-blocket, den sista står utanför och körs alltid. Experimentera sedan i tre steg: ändra poäng till 50 och kör, vilka rader körs inte? Lägg till fyra mellanslag framför print("Färdig.") och kör med 50 igen, varför försvann även den? Ta till sist bort hela indraget framför print("Betyg: A") och kör en sista gång.

Som du ser säger Python ifrån direkt. Indraget är inte ett formateringsval som kan ignoreras, det är en del av syntaxen, och stämmer det inte stannar programmet med ett IndentationError Ett syntaxfel som uppstår när ett kodblock har fel antal inledande mellanslag, eller när tabbar och mellanslag blandas i samma block. Se: Konsten att välja , ofta med en pilmarkering som pekar ut exakt raden.

Uppgift: Klädrådet

Skapa filen kladrad.py. Programmet frågar efter temperaturen ute och svarar med ett råd om vad man bör ha på sig.

  1. Fråga efter temperaturen och gör om svaret till ett heltal med int().

  2. Bygg en if/elif/else-kedja med minst fyra grenar, till exempel under noll, 0 till 9, 10 till 19 och 20 eller varmare. Varje gren skriver ut sitt eget råd. Gränserna bestämmer du själv, men skriv dem så att inget värde hamnar mellan två grenar.

  3. Kör programmet med ett värde i varje gren, och sedan med ett värde som ligger exakt på en av dina gränser. Hamnade det i den gren du tänkte?

  4. Det här är KlassificerarenMönsterkortet: ett värde in, en kategori ut. Öppna kortet och jämför din kedja med mönstret.

  5. Gå till Source Control-panelen i VS Code, stagea filen, skriv ett meningsfullt commit-meddelande och pusha.

Vad händer om

Flytta din mest tillåtande gren, den som släpper igenom flest värden, längst upp i kedjan. Kör sedan programmet med tre olika temperaturer. Vad får du för svar, och varför spelar ordningen roll när varje gren ser korrekt ut var för sig?

Motivera & reflektera

Motivera var du lade dina gränser. Hur säkerställde du att ett värde som ligger precis på en gräns hamnar i rätt gren, och inte i två eller ingen?