Osa 3

Ehdot silmukoissa

Edellisen osan lopussa opimme käyttämään while True -silmukkaa koodin toistamiseen. Tässä tapauksessa silmukan ehtona on True, joka on aina tosi. Esimerkiksi

# Tulosta lukuja kunnes muuttujan a arvo on 5
a = 1
while True:
    print(a)
    a += 1
    if a == 5:
        break
Esimerkkitulostus

1 2 3 4

Silmukan toimintaa voidaan monipuolistaa lisäämällä tarkasteltava ehto while-määrittelyyn. Yleisemmin voimme siis käyttää silmukkaa näin:

while <ehtolauseke>:
    <lohko>

Ideana on, että silmukka vuorotellen tarkastaa ehdon ja suorittaa lohkossa olevan koodin, jos ehto on tosi. Sitten kun ehto on epätosi, ohjelman suoritus jatkuu silmukan jälkeiseltä riviltä.

3 1 1

Esimerkiksi seuraavassa silmukassa ehtona on luku < 10 eli silmukan koodi suoritetaan, jos luku on alle 10.

luku = int(input("Anna luku: "))

while luku < 10:
    print(luku)
    luku += 1

print("Suoritus valmis.")

Ohjelman tulostus voi olla seuraava:

Esimerkkitulostus

Anna luku: 4 4 5 6 7 8 9 Suoritus valmis.

Koska ehto tarkastetaan aina ennen silmukan koodin suoritusta, on mahdollista, ettei koodia suoriteta kertaakaan. Esimerkiksi:

Esimerkkitulostus

Anna luku: 12 Suoritus valmis.

Koska 12 ei ole pienempi kuin 10, ohjelma ei tulosta yhtään lukua.

Alustus, testaus ja muutos

Monessa silmukassa on kolme osaa: alustus, ehto ja muutos.

Alustus tarkoittaa silmukassa käytettävän muuttujan tai muuttujien alkuarvojen antamista. Tämä vaihe tehdään ennen silmukkaa. Ehto kirjoitetaan silmukan alkuun, ja se määrittelee, kuinka kauan silmukkaa suoritetaan. Joka kierroksella tapahtuva muutos vie silmukan askeleen lähemmäs sen loppumista. Esimerkiksi:

3 1 2

Jos jokin kolmesta osasta puuttuu, silmukka ei toimi oikein. Yksi tyypillinen virhe on muutoksen unohtaminen:

luku = 1

while luku < 10:
    print(luku)

print("Suoritus valmis.")

Koska muuttujan luku arvo ei koskaan muutu, jää ohjelma suoritettaessa ikuiseen silmukkaan eli toistaa samaa koodia, kunnes käyttäjä katkaisee ohjelman suorituksen (esimerkiksi painamalla CTRL + C):

Esimerkkitulostus

1 1 1 1 1 (tämä jatkuu ikuisesti...)

Ehdoista tarkemmin

Silmukan ehtona voidaan käyttää mitä tahansa ehtolauseketta. Esimerkiksi seuraava ohjelma tulostaa lukuja kolmen välein niin kauan kuin luku on pienempi kuin 100 eikä se ole jaollinen 5:llä:

luku = int(input("Anna luku: "))

while luku < 100 and luku % 5 != 0:
    print(luku)
    luku += 3

Kaksi esimerkkitulostusta eri syötteillä:

Esimerkkitulostus

Anna luku: 28 28 31 34 37

Esimerkkitulostus

Anna luku: 96 96 99

Luvun 28 kohdalla silmukka päättyy lukuun 37, koska seuraava luku 40 on jaollinen 5:llä. Luvun 96 kohdalla silmukka päättyy lukuun 99, koska seuraava luku 102 ei ole alle 100.

Silmukan ehtoa kirjoittaessa on tärkeä varmistua siitä, että silmukan suoritus päättyy. Esimerkiksi seuraava ohjelma on joko päättyvä tai ei-päättyvä riippuen alkuarvosta:

luku = int(input("Anna luku: "))

while luku != 10:
    print(luku)
    luku += 2

Jos syötteenä on parillinen luku, joka on enintään 10, silmukan suoritus päättyy:

Esimerkkitulostus

Anna luku: 4 4 6 8

Muissa tapauksissa silmukka on kuitenkin ikuinen, koska muuttuja ei koskaan saavuta arvoa 10. Tällaisia syötteitä ovat esimerkiksi 3 ja 12.

Koodauksen workflow ja lisää välineitä debuggaukseen

Hieman haastavampaa ohjelmaa, esim. seuraavaksi vuorossa olevaa tehtävää Kahden potenssit, koodatessa voitaisiin lähteä liikkeelle seuraavasti:

asti = int(input("Mihin asti"))
luku = 1
while luku == asti:
   # koodia

eli aloitettaisiin syötteen lukemisesta ja ruvettaisiin sen jälkeen miettimään silmukan lopetusehtoa sekä silmukan toimintaa.

Todennäköisesti ohjelma ei ensimmäisillä kokeilukerroilla toimi ollenkaan halutulla tavalla ja koodia on testailtava kymmeniä tai jopa satoja kertoja ennen kun se alkaa toimia.

Koska koodi lukee syötteitä käyttäjältä, on sen toiminnan kokeileminen hidasta ja vaivalloista, koska jokaisella testauskerralla on ohjelmalle annettava näppäimistöltä käsin sen haluamat syötteet.

Yksi tapa toimia on "kovakoodata" syöte aluksi:

# kovakoodataan syötteen arvo aluksi
asti = 8 # int(input("Mihin asti"))
luku = 1
while luku == asti:
   # koodia

Kun ohjelma toimii yhdellä syötteellä, sitä on helppo kokeilla muilla kovakoodatuilla syötteillä ja lopulta lukemalla syöte käyttäjältä.

Vastaava kikka toimii myös kurssien tehtäviin liittyvien testien ongelmatilanteita selvitellessä. Jos testi kertoo, että ohjelmasi toimii väärin, kun syöte on vaikkapa 42, niin kovakoodataan se syötteeksi bugin etsinnän ajaksi:

# testi ilmoitti että koodi toimii väärin kun syöte on 42
asti = 42 # int(input("Mihin asti"))
luku = 1
while luku == asti:
   # koodia

Kurssin edellisessä osassa oli jo pariinkin otteeseen puhetta tulostuskomennon avulla tapahtuvasta debuggaamisesta. Kurssin aikana vastaan tulevat ohjelmat muuttuvat koko ajan haastavammiksi ja debuggauksen tarve tulee kasvamaan entisestään. Esimerkiksi silmukoiden lopetusehtojen saaminen toimimaan kaikissa tapauksissa voi olla haastavaa.

Tulostuskomentoihin perustuva debuggaus kannattaa ottaa omaan työkalupakkiin viimeistään nyt. Kertaa tarvittaessa edellisen osan ensimmäisessä ja neljännessä luvussa olleet debuggausohjeet.

Tulostelun lisäksi on olemassa muitakin debuggaukseen sopivia työkaluja. Eräs tälläinen on sivuston Python Tutorin tarjoama visualisointityökalu, jonka avulla oman ohjelman koodia on mahdollista suorittaa komento komennolta havainnoiden samalla, mitä arvoja ohjelman muuttujat saavat.

Seuraavassa kuva, kun Python Tutorilla visualisoidaan edellisen osan debuggausmateriaalissa olevan hieman rikkinäisen koodin toimintaa:

3 1 0

Punainen nuoli kertoo, missä kohtaa ohjelman suoritus on menossa. Visualisaattori näyttää, mitä ohjelma on tulostanut ruudulle ja mitkä ohjelman muuttujien arvot kulloisellakin suorituksen hetkellä ovat. Koodin suoritus etenee komento komennolta painiketta Next> painellessa.

Visualisaattorin käyttö on erittäin helppoa, koska riittää että tarkasteltava koodi kopioidaan täällä olevaan koodi-ikkunaan.

Huomaa, että visualisaattori ei saalli skandien (ä, ö) ja käyttöä muuttujien eikä funktioiden nimissä.

Kokeneemmat ohjelmoijat tuskin käyttävät visualisaattoria koskaan, mutta aloittelijalle se voi olla oiva apuväline. Ohjelmointi ei nimittäin voi perustua tuuriin tai sattumaan. Ohjelmoijan on koko ajan tiedettävä tarkalleen, mitä muuttujien arvot ohjelman suorituksen aikana ovat. Jos muuttujien arvot eivät vastaakaan sitä mitä ohjelmoija olettaa, on tuloksena mitä suurimmalla todennäköisyydellä bugi.

Visualisaattori ja debuggaustulostukset ovat erinomainen väline sille, että ohjelmoija voi helposti omin silmin varmistaa, että ohjelma todellakin toimii, niin kuin sen olettaa toimivan.

Merkkijonon rakentaminen paloista

Jo kurssin ensimetreillä opimme, että merkkijono on mahdollista "rakentaa" useammasta pienemmästä merkkijonosta +-operaattorin avulla. Esimerkiksi

sanat = "suo"
sanat = sanat + ", kuokka"
sanat = sanat + " ja python"

print(sanat)
Esimerkkitulostus

suo, kuokka ja python

Huomaa, että edellinen on mahdollista kirjoittaa hieman tiiviimmin operaattorin += avulla:

sanat = "suo"
sanat += ", kuokka"
sanat += " ja python"

print(sanat)

Yhdistettävä merkkijonon pätkä voi olla myös f-merkkijono. Tämä saattaa olla kätevää, jos rakennettavaan merkkijonoon lisätään muuttujissa olevia arvoja. Voimme siis tehdä esim. seuraavasti:

kurssi = "Ohjelmoinnin perusteet"
arvosana = 4

lausunto = "Olet saanut "
lausunto += f"kurssilta {kurssi} "
lausunto += f"arvosanan {arvosana}"

print(lausunto)
Esimerkkitulostus

Olet saanut kurssilta Ohjelmoinnin perusteet arvosanan 4

Edellisessä tehtävässä laskettiin lukujen summaa kasvattamalla sen arvoa silmukan sisällä.

Täsmälleen samalla idealla on mahdollista rakentaa myös merkkijonoa siten, että siihen lisätään yksi osa kerrallaan silmukassa...

:
Loading...
:
Loading...

Log in to view the quiz