Tsükkel ehk korduslause
Kui meil on vaja teha sama toimingut mitu korda järjest, siis võiks arvata, et programmi tuleb kirjutada laused lihtsalt mitmekordselt nagu järgmises programmis
print("Võistlus hakkab 4 sekundi pärast") print("4") print("3") print("2") print("1") print("Start")
Selline lahendus muutub aga väga kohmakaks, kui korduste arv läheb suureks. Pealegi see lahendus ei sobi siis, kui sooviksime kirjutada üldisema programmi, kus saame anda programmile ette aja, millal võistlus hakkab, näiteks 25 sekundit.
Siinkohal tulevad appi tsüklid (e korduslaused), mis on programmikonstruktsioonid käskude kordamiseks.
Etteruttavalt näide, kuidas while-tsükliga antud ülesannet lahendada saaks:
aeg = 25 while aeg > 0: print(aeg) aeg -= 1
Antud programm loeb sekundeid alla nii palju kui suur on muutuja aeg. Hetkel 25-st 1-ni.
Märkus! aeg -= 1 tähendab täpselt sama, mis aeg = aeg - 1. See on Pythoni lühend, mis aitab kiiremini ja kergemalt muutujat mingi konstandi võrra muuta. See toimib teiste matemaatiliste tehetega ka nagu korrutamine, jagamine jne. Näiteks aeg *= 3 on sama mis aeg = aeg * 3.
while-lause
while-lause keha täidetakse vaid siis, kui päises antud tingimus kehtib. Selles suhtes on while väga sarnane üheharulise if-lausega. Erinevus on selles, et kui kehas olevad laused on täidetud, siis minnakse uuesti päises näidatud tingimust kontrollima – kui tingimus kehtib ikka veel, siis täidetakse kehas olevad laused uuesti jne. Kui lõpuks tingimus enam ei kehti (eelnevas näites kui 25 korda on number väljastatud), minnakse edasi while-lausele järgnevate lausetega.
Korduslauseid kasutades tuleb kindlalt ära määrata sündmus, mille tagajärel tsükkel tegevuse lõpetab. Vastasel juhul võib programm lõpmatuseni sama tegevust korrata.
Proovige, mis juhtub kui käivitate lõpmatu tsükli Thonnys
muutuja = 1 while 1 > 0: muutuja *= 2 print(muutuja)
Antud programmil ei ole loodud tingimust, millal tegevuse kordamine lõpetatakse. While-lause päises kontrollitakse, kas 1 on suurem kui 0. Kuna see vastab tõele, siis korratakse tsükli kehas toimuv tegevus lõpmatult. Suure tõenäosusega jookseb teil Thonny selle peale kokku.
Selleks, et halvasti loodud korduslause programmi või halvemal juhul arvutit kokku ei jooksutaks, kasutatakse muutujat, mis tsükli täitmisel muutub. Kui muutuja on saavutanud mingi kindla oleku, siis tsükkel lõpetatakse.
muutuja = 0 while muutuja < 30: muutuja += 5 print(muutuja)
Programmi on muudetud nii, et iga kord suureneb muutuja viie võrra. Lisaks on nüüd while-lause päis ära muudetud. Iga kord kontrollitakse, kas muutuja on väiksem kui 30. Kui muutuja muutub suuremaks kui 30, siis tsükli sisu enam ei täideta.
Enne katsetamist proovi ära arvata, mis arvud ekraanile väljastatakse.
Tähelepanu!!! Kui arvu- või sõneoperatsioonides (e tehetes) kasutada muutujaid (nt n + 1 või tekst.upper()), siis võib avaldise kujust jääda mulje, et operatsiooni käigus muudetakse muutuja väärtust. Tegelikult genereeritakse tehte tulemusena hoopis uus väärtus ja kasutatud muutujaga midagi ei juhtu. Selles veendumiseks uuri järgmisi käsurea näiteid, kus kõigepealt omistatakse muutujale mingi väärtus, seejärel kasutatakse muutujat mingis tehtes (mis konstrueerib uue väärtuse) ning lõpuks demonstreeritakse, et see ei mõjutanud muutuja väärtust:
>>> n = 3 >>> n + 2 5 >>> n 3 >>> sõna = ' kala ' >>> sõna.strip() 'kala' >>> sõna ' kala ' >>> tekst = '3' >>> int(tekst) 3 >>> tekst '3'
While-tsükli video
Enesekontroll
for-tsükkel
Lisaks while-tsüklile on Pythonis veel üks tsüklitüüp – for-tsükkel.
for i in range(3): print("Tere")
Antud näide väljastab ekraanile Tere 3 korda.
Nagu näed, sarnaneb for-tsükkel kuju poolest while-tsükliga – esimesel real on päis, mis määrab korduste arvu, ning edasi tuleb taandreaga esitatud keha, mis sisaldab lauseid, mida igal kordusel käivitatakse. For-tsüklit saab nimetada määratud tsükliks, sest päises määratakse kindel arv, kui palju kordi tsüklit läbitakse.
For-tsükkel erineb while-tsüklist peamiselt selle poolest, et talle saab anda ette järjendeid. Järjend võib olla näiteks muutuja, mis hoiab endas numbreid või sõnu.
järjend = [12, 24, 72] või Järjend = ["Lennart", "Hendrik", "Päts"] Järjendeid õpime lähemalt 7-ndal nädalal.
for-tsükli kordused põhinevad mingil etteantud järjendil. Igal kordusel küsitakse järjendist üks element, salvestatakse tema väärtus tsüklimuutujasse ning seejärel käivitatakse tsükli kehas olevad laused. Elemente loetakse järjendist järjekorras, st esimesel kordusel esimene element jne. Kui kõik elemendid on sedasi läbi käidud, siis on tsükli töö tehtud – seega käivitatakse tsükli keha niipalju kordi kui on järjendis elemente.
järjend = ["Lennart", "Hendrik", "Päts"] for nimi in Järjend: print("Tere, " + nimi + "!")
Sellisel juhul väljastatakse ekraanile:
Tere, Lennart! Tere, Hendrik! Tere, Päts!
Miks „for“?
Mõnedes programmeerimiskeeltes nimetatakse for-tsüklit hoopis for-each-tsükliks, sest tsükli keha täidetakse päises näidatud järjendi iga elemendi jaoks uuesti. Pythonis on otsustatud lühema nime „for“ kasuks.
range
Eelnevalt näites kasutasime avaldist range, mis genereerib ühe järjendit meenutava väärtuse – nimelt vahemiku 0..2. Järgnevas näites teisendab funktsioon list selle väärtuse päris järjendiks, mis sisaldab täisarve 0..4.
Näiteks:
>>> list(range(5)) [0, 1, 2, 3, 4]
Nüüd peaks olema selge, miks meie for-tsükli näide sedasi käitus – range(3) genereerib vahemikku 0..2 kujutava väärtuse ja kuigi tegemist pole päris järjendiga, oskab for-tsükkel seda käsitleda justkui järjendit. Edasi toimub kõik samamoodi nagu varem kirjeldatud – pseudo-järjendist loetakse ükshaaval elemente, mis salvestatakse kordamööda tsüklimuutujasse i ning igal kordusel käivitatakse tsükli kehas olevad laused.
Korduslause video
Enesekontroll
break
Tsükli lõpetamise määrab tavaliselt tsükli päises olev tingimus. Sellele lisaks on Pythonis veel üks võimalus tsükli töö lõpetamiseks – selleks tuleb tsükli kehas anda sobival hetkel käsk break.
summa = 0 arvutusi = 0 while summa < 1000: if arvutusi >= 5: print("Ei saanud 1000 kokku") break liidetav = int(input("Sisesta arv, mida liita: ")) summa = summa + liidetav # Võib kirjutada ka: summa += liidetav print("Praegune summa on: " + str(summa)) arvutusi += 1
Antud näites soovime, et programm küsiks kasutajalt numbreid. Ta kasutab neid, et arvutada kõikide arvude summat. Programm lõpetab, kui summa läheb üle 1000 või kui kasutaja on andnud 5 arvu.
Tegelikult pole break-lause Pythoni programmides hädavajalik - tsükli saab alati ümber kirjutada nii, et kõiki jätkamise/lõpetamise tingimusi kontrollitakse tsükli päises, aga vahel on break-iga lahendus lihtsam.
Mõnikord on mugav tsükli lõpetamise tingimust kontrollida ainult tsükli kehas, sel juhul pannakse tsükli päisesse alati kehtiv tingimus True. Järgnev näide arvutab ringi pindala etteantava raadiusega.
while True: raadius = input("Mis on ringi raadius? Lõpetamiseks vajuta ENTER: ") if raadius == "": break else: pindala = 3.14 * int(raadius) * int(raadius) print("Ringi pindala on: " + str(pindala))
Kasutaja saab ise valida, kui kaua ta programmi kasutada tahab.
continue
Vahel võib juhtuda, et peale lõpetamise tingimuse võib ette tulla olukord, kus me soovime tsükli täitmist kindlate andmete puhul vältida. Sõna continue katkestab tsükli jooksva sammu täitmise ja jätkab tsükli täitmist muutuja järgmise väärtusega.
Soovime leida paaritud arvud kuni 10ni.
for arv in range(10): if arv % 2 == 0: continue print("Tegu on paaritu arvuga " + str(arv))
Enesekontroll
Erindite püüdmine try
-lausega
Vaatame ühte lühikest ja lihtsat programmi:
arv1 = float(input("Sisesta esimene arv: ")) arv2 = float(input("Sisesta teine arv: ")) print("Nende arvude jagatis on", arv1 / arv2)
Mis juhtub siis, kui kasutaja sisestab ühe soovitud arvu (nt. 45) asemel kogemata midagi, millest Python ei oska arvu välja lugeda (näiteks 45t)? Proovi järele!
Ilmselt nägid, et Python väljastas ekraanile veateate, ning lõpetas programmi töö. Selle programmi puhul polnud see suur õnnetus, aga keerulisemates programmides, kus kasutaja on suure ülesandega poole peale jõudnud, oleks üpris kahju kui selline väike aps programmi sulgeks. Seetõttu on Pythonisse loodud võimalused täitmisaegsete vigade e erindite „püüdmiseks“.
Vigade püüdimiseks tuleb kasutada try-lauset. Alustame näitest:
try: arv1 = float(input("Sisesta esimene arv: ")) arv2 = float(input("Sisesta teine arv: ")) print("Nende arvude jagatis on", arv1 / arv2) except: print("Hmm..., midagi läks vussi.")
Nii nagu if-else-lause, koosneb ka try-lause mitmest osast – võtmesõna try alla kirjutatakse laused, mida soovitakse normaalsel juhul täita ning võtmesõna except alla laused, mida täidetakse siis, kui try-osa lausete täitmisel tekib mingi viga (siit ka võtmesõna except – neid lauseid soovime täita vaid erandjuhtumitel).
Antud näite puhul on küsitav, kuivõrd try-lause lisamine midagi paremaks tegi – me küll peitsime kasutaja eest ära koleda mitmerealise veateate (kas see peitmine oli üldse hea?), aga vigase sisestuse korral jäi kasutaja ikkagi vastusest ilma. Koodi kavalalt ümber paigutades saame me aga programmi, mis küsib kasutajalt arve niikaua, kuni lõpuks teisendamine ja jagamine õnnestub:
while True: try: arv1 = float(input("Sisesta esimene arv: ")) arv2 = float(input("Sisesta teine arv: ")) print("Nende arvude jagatis on", arv1 / arv2) break except: print("Hmm..., midagi läks vussi.") print("Proovime uuesti!")
Siin me panime kogu programmi loogika tsüklisse, millest pääseb välja käsuga break. Selle käsuni jõuab Python aga ainult siis, kui kõik try-osa laused edukalt läbitakse – niipea, kui kusagil eespool tekib mingi viga, hüpatakse kohe except-osasse ning peale selle täitmist jätkatakse uuesti tsükli algusest.
Hoiatus!
Vigade kinnipüüdmine on põhjendatud ainult siis, kui sa tõesti oskad selle veasituatsiooniga midagi ette võtta. Vigu ei tohiks püüda kinni lihtsalt selleks, et vältida veateate ekraanile jõudmist – see võib tekitada situatsiooni, kus programmis on mingi probleem, aga ei programmeerija ega kasutaja ei saa sellest teada ning programm annab süüdimatult välja valed tulemused.