Den eviga loopen
Vad händer om du aldrig avbryter?
Varje program du skrivit hittills har levt i exakt ett svar. Vi frågar, något sker, programmet är slut. Vill användaren göra om det måste hela programmet startas om från terminalen. Och det finns en hel kategori av program som inte kan fungera så: ett program som ska köra tills användaren väljer att avsluta, ett spel som ska pågå tills en spelare vinner, en server som ska lyssna efter inkommande anrop tills den stängs av manuellt. Inget av dem vet på förhand hur länge det ska hålla på.
I Vägskälet lovade vi att den tredje förmågan, att upprepa, väntade i det här temat. Här är den. En while-loop En loop som kör sitt kodblock upprepade gånger så länge ett villkor är sant. Till skillnad från en for-loop har den inget förutbestämt antal varv. fortsätter köra så länge ett villkor är sant, och i sin mest extrema form, while True:, fortsätter den tills något inuti loopen aktivt bryter ur den. Det är en loop utan naturlig slutpunkt, och det kräver att du som programmerare bestämmer exakt när och hur den ska avslutas.
Varje varv loopen kör kallas en Iteration Ett varv i en loop. En loop som kör fem varv gör fem iterationer, och loopkroppen körs en gång per iteration. När loopen går igenom en samling besöker den ett element per iteration. . Ordet betyder bara upprepning, och det är enheten man räknar loopar i: en loop som kör fem varv gör fem iterationer. Raderna som är indragna under while-raden är Loopkropp Alla rader som är indenterade under for-satsen. Körs en gång per element, i ordning. , och den körs en gång per iteration. Du kommer att se ordet i felmeddelanden, i dokumentation och i resten av den här kursen, så det är värt att äga från början.
Gör du det inte, om du skriver while True: utan ett sätt att ta dig ur, har du bett datorn att göra samma sak för evigt. Det är inte ett hypotetiskt problem. Det händer. Och det är värt att veta vad som faktiskt händer i hårdvaran när det sker.
Det som händer i hårdvaran
Den här koden får ingen sandlåda på sidan, och det är med flit. Poängen är att lyssna på din egen dator och titta på dess processor, och ingetdera går i en webbläsare. Öppna en ny fil i VS Code, skriv det här och kör det. pass är ett tomt kommando som gör ingenting alls, men varje varv kostar CPU-tid:
while True:
pass Tryck Ctrl+C efter några sekunder. Titta på datorns fläktar, hör du dem snurra upp? Öppna aktivitetsövervakaren (macOS) eller aktivitetshanteraren (Windows) och leta efter Python-processen. CPU-belastning Andelen av processorns kapacitet som används av ett program. En oändlig loop utan arbete driver en kärna till 100% belastning och genererar värme som en direkt konsekvens av elektrisk ström genom transistorer. för en kärna är troligen nära 100%.
Det är inte en bugg i hårdvaran. Det är exakt vad du beställde. Varje pass är en instruktion som processorn exekverar. Miljoner instruktioner per sekund, utan paus. Elektrisk ström genom miljarder transistorer genererar värme som en naturlag, och datorn svarar med att kyla sig aktivt.
Hjälp, stop!
Ctrl+C i terminalen skickar en avbrottssignal till det körande programmet. Python tar emot signalen och kastar ett KeyboardInterrupt Ett undantag som Python kastar när användaren trycker Ctrl+C i terminalen. Stoppar programmet omedelbart om det inte fångas av ett try/except-block. , ett undantag som stoppar programmet omedelbart om det inte fångas upp explicit.^C
Traceback (most recent call last):
File "loop.py", line 2, in <module>
pass
KeyboardInterrupt Det ser ut som ett felmeddelande men det är inte ett programmeringsfel, det är en kontrollerad nödstopp. Lär dig det här snabbt: det sparar dig från att behöva stänga hela terminalfönstret varje gång en loop kör iväg.
while True med break, kontrollerad loop
Den korrekta lösningen på en loop utan känd slutpunkt är while True: med ett break inuti ett villkor. break Ett nyckelord som omedelbart avslutar den innersta loop det befinner sig i. Exekveringen hoppar till första raden efter loopkroppen. avslutar loopen omedelbart, exekveringen hoppar direkt till första raden efter loopkroppen:
Redo.
Inmatningsrutan innehåller tre rader: ja, ja och sedan nej. Kör koden och räkna utskrifterna. Loopen kör tre varv, ett per rad, och bryter på det tredje. Lägg till fler ja-rader före nej och kör igen, loopen bryr sig inte om hur många det är. Ta sedan bort break-raden och kör en sista gång: nu tar inmatningen slut medan loopen fortfarande vill ha mer.
Loopen kör tills användaren skriver "nej". Ingen räknare, ingen lista, ingen förutbestämd slutpunkt, bara ett villkor som kan bli sant vid vilken iteration som helst.
Menyn, ett program som väntar på sin användare
Nu kan du bygga programmet som nästan alla terminalprogram är: en meny som visar sina alternativ, tar emot ett val, gör något och frågar igen. Det är elif-kedjan du redan kan, placerad inuti loopen du precis lärt dig.
Redo.
Kör koden. Inmatningsrutan väljer först 1 och sedan 4, så du ser saldot och sedan avslutningen. Tre saker gör menyn till en meny, och alla tre sitter i loopen:
Utskrifterna ligger inuti loopen, därför visas alternativen på nytt inför varje val. Alternativet Avsluta bär ett break, det är den enda vägen ut. Och else-grenen fångar allt annat användaren råkar skriva utan att avsluta något, den skriver bara ut ett meddelande och låter nästa varv börja.
Prova att lägga till fler rader i inmatningsrutan, till exempel 9 före 4, och se hur else-grenen svarar utan att programmet ger upp.
while med ett villkor
while True: med break är ett mönster, inte ett krav. Alternativet är att skriva villkoret direkt i while-satsen. Villkoret är av exakt samma sort som i ett if, och byggs med samma jämförelseoperatorer, hela tabellen finns i Vägskälet:
spelet_aktivt = True
while spelet_aktivt:
val = input("Välj: ")
if val == "avsluta":
spelet_aktivt = False
print("Spelet är slut.") Båda varianterna fungerar. while True: med break är ofta rakare för menyer och dialoger. while villkor: är ofta tydligare för spellooppar där flera olika händelser kan avsluta loopen, villkoret i while-raden berättar direkt vad som håller loopen vid liv.
Uppgift: Menyn som inte ger upp
Skapa filen meny.py.
Bygg en egen meny med minst tre alternativ inuti en
while True:-loop. Både utskrifterna ochinput()ska ligga inne i loopen. Vad alternativen handlar om bestämmer du själv, det behöver inte vara ett banksystem.Se till att ett av menyalternativen är “Avsluta” och att det alternativet innehåller ett
breaksom faktiskt avbryter loopen. Skriv ut ett avskedsmeddelande innanbreak.Lägg till ett
else-block som hanterar ogiltiga inmatningar med ett tydligt meddelande, utan att avsluta loopen.Gå till Source Control-panelen i VS Code, stagea filen, skriv ett meningsfullt commit-meddelande och pusha.
Vad händer om
Ta bort break från “Avsluta”-alternativet och kör programmet. Vad händer när du väljer “Avsluta”? Hur stoppar du programmet, och vad säger det om varför break inte är valfritt i det här mönstret?
Motivera & reflektera
Motivera ditt val mellan while True: med break och while villkor:. Varför passade den form du valde för just din meny?