Yksinkertainen silmukka
Silmukka eli toistolause on ehtolauseen lisäksi keskeinen ohjausrakenne ohjelmoinnissa. Aloitetaan toistamiseen tutustuminen tarkastelemalla Pythonin while
-silmukkaa yksinkertaisten esimerkkien kautta. Ensi viikolla tutustutaan sitten monipuolisemmin sen mahdollisuuksiin.
Periaatteessa silmukka muistuttaa ehtolausetta. Ideana kuitenkin on, että sen avulla voidaan toistaa samaa koodia useamman kerran.
Tarkastellaan esimerkkiä, jossa ohjelma laskee käyttäjän syöttämien lukujen neliöitä, kunnes käyttäjä syöttää luvun -1:
while True:
luku = int(input("Anna luku, -1 lopettaa: "))
if luku == -1:
break
print(luku ** 2)
print("Kiitos ja moi!")
Ohjelman esimerkkisuoritus:
Anna luku, -1 lopettaa: 2 4 Anna luku, -1 lopettaa: 4 16 Anna luku, -1 lopettaa: 10 100 Anna luku, -1 lopettaa: -1 Kiitos ja moi!
Kuten esimerkistä huomataan, ohjelma kysyy while
-lauseen ansiosta käyttäjältä useita lukuja. Sitten kun käyttäjän syöte on -1, suoritetaan break
-komento, jolloin suoritus hyppää ensimmäiselle lohkon jälkeiselle riville.
Silmukoita käytettäessä on oltava tarkkana, että ei jouduta tilanteeseen, missä silmukan suoritus ei koskaan lopu. Muutetaan edellistä esimerkkiä seuraavasti
luku = int(input("Anna luku, -1 lopettaa: "))
while True:
if luku == -1:
break
print(luku ** 2)
print("Kiitos ja moi!")
Nyt siis lukua kysytään silmukan ulkopuolella. Jos käyttäjä antaa minkä tahansa muun luvun kuin -1:n, ei silmukasta tulla koskaan pois, eli syntyy ikuinen silmukka. Tällöin silmukassa olevaa lohkoa suoritetaan ikuisesti:
Anna luku, -1 lopettaa: 2 4 4 4 4 4 4 4 4 (jatkuu ikuisesti...)
Seuraavassa esimerkkinä ohjelma, joka antaa käyttäjän jatkaa eteenpäin vasta sen jälkeen, kun käyttäjä on syöttänyt oikean PIN-koodin 1234:
while True:
koodi = input("Anna PIN-koodi: ")
if koodi == "1234":
break
print("Väärin... yritä uudelleen")
print("PIN-koodi oikein!")
Anna PIN-koodi: 0000 Väärin... yritä uudelleen Anna PIN-koodi: 9999 Väärin... yritä uudelleen Anna PIN-koodi: 1234 PIN-koodi oikein!
Silmukka ja apumuuttujat
Tehdään vielä PIN-koodin tarkastavasta ohjelmasta monimutkaisempi versio, joka antaa käyttäjälle vain kolme mahdollisuutta yrittää PIN-koodin syöttämistä.
Ohjelma käyttää nyt kahta apumuuttujaa. Muuttuja yritykset
pitää kirjaa siitä, montako kertaa käyttäjä on syöttänyt koodin. Muuttuja onnistui
saa arvokseen joko True
tai False
riippuen siitä, onnistuuko kirjautuminen.
yritykset = 0
while True:
tunnus = input("Anna PIN-koodi: ")
yritykset += 1
if tunnus == "1234":
onnistui = True
break
if yritykset == 3:
onnistui = False
break
# tänne tullaan jos väärin JA ei ole jo kolmea yritystä
print("Väärin... yritä uudelleen")
if onnistui:
print("PIN-koodi oikein!")
else:
print("Liian monta yritystä...")
Anna PIN-koodi: 0000 Väärin... yritä uudelleen Anna PIN-koodi: 1234 PIN-koodi oikein!
Anna PIN-koodi: 0000 Väärin... yritä uudelleen Anna PIN-koodi: 9999 Väärin... yritä uudelleen Anna PIN-koodi: 4321 Liian monta yritystä...
Silmukasta tullaan siis ulos, jos käyttäjä syöttää oikean PIN-koodin tai jos yrityksiä tehdään liian monta. Silmukan jälkeinen if-lause tarkastaa muuttujan onnistui
arvon perusteella, onko kirjautuminen onnistunut vai ei.
Debug-tulostus silmukassa
Kun ohjelma sisältää silmukoita, kasvavat mahdolliset bugienkin lähteet uudelle tasolle, ja tämän osan ensimmäisessä luvussa mainittujen debug-tulostusten tekeminen muuttuu entistäkin tärkeämmäksi.
Tarkastellaan esimerkkiä, jossa edellinen ohjelma on koodattu hieman väärin:
yritykset = 0
while True:
tunnus = input("Anna PIN-koodi: ")
yritykset += 1
if yritykset == 3:
onnistui = False
break
if tunnus == "1234":
onnistui = True
break
print("Väärin... yritä uudelleen")
if onnistui:
print("PIN-koodi oikein!")
else:
print("Liian monta yritystä...")
Ohjelma toimii kummallisesti: se antaa yrittää PIN-koodia kolmesti mutta valittaa, että yrityksiä on liian monta, vaikka lopussa syötettiin oikea koodi:
Anna PIN-koodi: 0000 Väärin... yritä uudelleen Anna PIN-koodi: 9999 Väärin... yritä uudelleen Anna PIN-koodi: 1234 Liian monta yritystä...
Bugin syy selviää lisäämällä sopivia debug-tulostuksia:
while True:
print("whilen lohko alkaa:")
tunnus = input("Anna PIN-koodi: ")
yritykset += 1
print("yritykset:", yritykset)
print("ehto1:", yritykset == 3)
if yritykset == 3:
onnistui = False
break
print("tunnus:", tunnus)
print("ehto2:", tunnus == "1234")
if tunnus == "1234":
onnistui = True
break
print("Väärin... yritä uudelleen")
whilen lohko alkaa: Anna PIN-koodi: 2233 yritykset: 1 ehto1: False tunnus: 2233 ehto2: False Väärin... yritä uudelleen whilen lohko alkaa: Anna PIN-koodi: 4545 yritykset: 2 ehto1: False tunnus: 4545 ehto2: False Väärin... yritä uudelleen whilen lohko alkaa: Anna PIN-koodi: 1234 yritykset: 3 ehto1: True Liian monta yritystä...
Tulostuksista huomataan, että kolmannella silmukan kierroksella ensimmäisen if
-komennon ehto on tosi ja silmukasta poistutaan, ennen kuin ehditään tarkastaa, oliko juuri syötetty salasana oikein:
while True:
# ....
# tämä lohko on liian aikaisin
if yritykset == 3:
onnistui = False
break
# tänne ei päästä enää kolmannella yrityksellä...
if tunnus == "1234":
onnistui = True
break
Merkkijonon kokoaminen plus-operaattorilla
PIN-koodin tarkastavassa esimerkissä käytimme apumuuttujaa yritykset
pitämään kirjaa siitä, montako kertaa PIN-koodi on syötetty:
yritykset = 0
while True:
tunnus = input("Anna PIN-koodi: ")
yritykset += 1
# ...
Muuttuja saa arvon nolla silmukan ulkopuolella, ja jokainen silmukan suoritus kasvattaa sen arvoa yhdellä.
Vastaava idea toimii myös merkkijonoille. Voisimme laajentaa ohjelmaa siten, että se kokoaa yhteen merkkijonoon kaikki käyttäjän syöttämät PIN-koodit:
tunnukset = ""
yritykset = 0
while True:
tunnus = input("Anna PIN-koodi: ")
yritykset += 1
tunnukset += tunnus + ", "
# ...
Apumuuttuja saa aluksi arvokseen tyhjän merkkijonon eli merkkijonon, jossa ei ole yhtään merkkiä:
tunnukset = ""
Silmukan sisällä merkkijonoa kasvatetaan lisäämällä siihen aina silmukassa syötetty tunnus ja pilkku:
tunnus = input("Anna PIN-koodi: ")
tunnukset += tunnus + ", "
Jos käyttäjä syöttäisi tunnukset 1111 2222 1234 olisi muuttujan tunnukset
arvo lopulta
1111, 2222, 1234,
Log in to view the quiz
Vastaa lopuksi koko toista osaa koskevaan loppukyselyyn:
Log in to view the quiz