Loeng 5: Määramata ja määratud itereerimine, while ja for tsüklid/blokid, lausendid: continue, break, funktsioonid input ja enumerate, iteraatortoega andmetüübid¶

Viimati uuendatud 30.09.2024.

Koodinäited¶

Itereerimine Pythonis¶

Itereerimine hõlmab endas teatud koodi osa (mitmekordset) taaskasutamist. Programmi struktuuri mis seda teostab nimetame iteratsioonitsükkliks. Programmeerimises eristame kahte tüüpi tsükkleid: määramata ja määratud.

Määramata iteratsioon: while-tsükkel (indefinite iteration: while-loop)¶

Määramata tsükklis on iteratsioonide arv esitatud ilmutamata kujul. Me kordame teatud tegevust seni kuni etteantud tingimus on rahuldatud. Joonis 1 kujutab määramata iteratsiooni ehk while-tsükli voodiagrammi. Määratud iteratsiooni tsüklis on iteratsioonide arv ilmutatud kujul teada tsükli käivitamise hetkel.

No description has been provided for this image
Joonis 1: while-tsükli voodiagramm.
In [1]:
n = 0
while n < 5:  # NB! koolon ja taane.
    n += 1    # Sama mis n = n + 1.
    print(n, end=' ')  # Uuri funktsiooni print abiinfot.
1 2 3 4 5 
In [2]:
n = 3
while n > 0:
    print(n)
    n -= 1  # Sama mis n = n - 1.
3
2
1
In [3]:
i = 0
lst = [12, 11, 10]
while i != len(lst):  # Sisseehitatud funk. len.
    print(lst[i])
    i += 1
12
11
10
In [4]:
while False:  # Kui True: lõpmatu tsükkel.
    print('Python')

while-break konstruktsioon¶

Lausend break murrab protsessi tsüklist välja. Lausend break peatab iteratsiooni protsessi. Tavaliselt esineb see lausend koos tingimuslausega. Joonis 2 kujutab while-break konstruktsioon voodiagrammi.

No description has been provided for this image
Joonis 2: while-tsüklis oleva while-break konstruktsiooni voodiagramm.
In [5]:
n = 6
while n > 0:
    n -= 1
    if n == 2:
        break
    print(n)

print('Oleme tsüklist väljas.')
5
4
3
Oleme tsüklist väljas.

Näide: Pangaautomaadi versioon 1 ja sisseehitatud funktsiooni input tutvustus.

In [6]:
raha_masinas = 3
raha_soov = int(input('Kui palju raha tahad?'))  # Sisseehitatud funk. input.

i = 1
while i <= raha_soov:
    if i > raha_masinas:
        print('Masinas sai raha otsa. Vabandame.')
        break
    print('1 euro')
    i += 1

print('Head aega.')
1 euro
1 euro
1 euro
Masinas sai raha otsa. Vabandame.
Head aega.

while-continue konstruktsioon¶

Lausend continue peatab hetkel teostatavat iteratsiooni ja alustab järgmise iteratsiooni tsükliga. Tavaliselt esineb see lausend koos tingimuslausega. Joonis 3 kujutab while-continue konstruktsiooni voodiagrammi.

No description has been provided for this image
Joonis 3: while-tsüklis oleva while-continue konstruktsiooni voodiagramm.
In [7]:
n = 4
while n > 0:
    n -= 1
    if n == 2:
        continue  # Liigume tsükli või uue iteratsiooni algusesse.
    print(n, 'minutit.')
3 minutit.
1 minutit.
0 minutit.

Näide: Täisarvud ühe ja kolmekümmne vahel mis EI jagu kolmega.

In [8]:
i = 1
while i <= 30:
    if i % 3 == 0:
        i += 1
        continue
    print(i, end=' ')
    i += 1
1 2 4 5 7 8 10 11 13 14 16 17 19 20 22 23 25 26 28 29 
No description has been provided for this image
Joonis 4: while-tsüklis oleva while-continue-break konstruktsiooni voodiagramm.

Näite: Lausendite continue ja break kasutamine ühes while-tsüklis. Alloleva näite põhimõtteline voodiagramm on kujutatud Joonisel 4.

In [9]:
i = 0
while i < 10:
    i += 1
    if i <= 3:
        continue
    elif i > 6:
        break
    print(i)
4
5
6

while-else konstruktsioon¶

Python lubab lisada lausendi else while-tsükli lõppu. Tegevus mis kaasneb else lausendiga teostatakse juhul kui kõik while-tsükli iteratsioonid on teostatud (tsükkel on ammendunud), st., et lausend break pole enneaegselt tsüklit lõpetanud. Joonised 5 ja 6 kujutavad while-else konstruktsiooni voodiagramme juhul kui tsüklis ei esine lausendit break ja kui see esineb.

No description has been provided for this image
Joonis 5: while-tsüklis oleva while-else konstruktsiooni voodiagramm.
In [10]:
n = 4
while n > 0:
    n -= 1
    print(n)
else:
    print('Tsükkel ammendus.')
3
2
1
0
Tsükkel ammendus.
No description has been provided for this image
Joonis 6: while-tsüklis oleva while-break-else konstruktsiooni voodiagramm.
In [11]:
n = 5
while n > 0:
    n -= 1
    print(n)
    if n == 2:  # Peatub enneaegselt.
        break
else:
    print('Tsükkel lõpetatud.')  # NB! Ei prindi, vt. Joonis 6.
4
3
2

Näide: Leia vahemikus $[1, n]$ kus täisarv $n > 1$ olevate arvude seast esimene viiega jaguv arv. Prindi see konsooli. Kui arvude seas puudub viiega jaguv arv prindi sellekohane teade (ainult üks kord) kasutades ühte while-tsüklit.

Vale lahendus võrdluseks:

In [12]:
mitu_arvu = 3
i = 0
while i < mitu_arvu:
    i += 1
    if i % 5 == 0:
        print(i)
        break
    else:
        print('[Vale] Arvu ei leitud.')  # Vale, prindib mitu korda.   
[Vale] Arvu ei leitud.
[Vale] Arvu ei leitud.
[Vale] Arvu ei leitud.

Õige lahendus:

In [13]:
mitu_arvu = 3
i = 0
while i < mitu_arvu:
    i += 1
    if i % 5 == 0:
        print(i)
        break
else:
    print('[Õige] Arvu ei leitud.')  # Õige, prindib üks kord.
[Õige] Arvu ei leitud.

Näide: Pangaautomaat versioon 2.

In [14]:
raha_masinas = 3
raha_soov = int(input('Kui palju raha tahad?'))

i = 1
while i <= raha_soov:
    if i > raha_masinas:
        print('Masinas sai raha otsa. Vabandame.')
        break
    print('1 euro')
    i += 1
else:
    print('Head aega.')  # Pole mõtet head päeva soovida kui raha ei antud.
1 euro
1 euro
1 euro
Masinas sai raha otsa. Vabandame.

Pesastatud while-tsükkel¶

while-tsükleid saab üksteise sisse pesastada. Joonis 7 kujutab while-tsüklisse pesastatud while-tsükli voodiagrammi.

No description has been provided for this image
Joonis 7: while-tsüklisse pesastatud while-tsükli voodiagramm. Pesastatud tsükkel on tähistatud rohelise kõveraga.
In [15]:
i = 0
j = 2
while i < 4:
    i += 1
    while j > 0 and i == 3:
        print('Pesastatud:', j)
        j -= 1
    print(i)
1
2
Pesastatud: 2
Pesastatud: 1
3
4

Näide: Nädal ja nädalapäevade tunnid.

In [16]:
päevad = ['E', 'L', 'P']
päeva_pikkus = 2  # Tundides.

i = 0
while i < len(päevad):
    print(päevad[i])
    tund = 0
    while tund <= päeva_pikkus:
        print(f'kell on {tund}.')
        tund += 1
    i += 1

print('\nUus nädal.')
E
kell on 0.
kell on 1.
kell on 2.
L
kell on 0.
kell on 1.
kell on 2.
P
kell on 0.
kell on 1.
kell on 2.

Uus nädal.

Määratud iteratsioon: for-tsükkel (definite iteration: for-loop)¶

Pythoni for-tsükli abil loome määratud iteratsiooni kus iteratsioonide arv on itereerimise alguses ilmne. Määratud iteratsiooni tsüklis ehk for-tsüklis itereeritakse üle etteantud iteraatortoega objektide või jadade (iterables). Joonis 8 kujutab for-tsükli voodiagrammi.

Iteraatortoega andmetüübid ja nende objektid on:

  • sõne
  • list (järjend, loend)
  • korteez
  • sõnastik
  • hulk
  • vahemik - range, range([<start>,] <stop>, [<step>])
No description has been provided for this image
Joonis 8: for-tsükli voodiagramm. Kriipjoonega tähistatud tegevused (indeksi i inkrementeerimine) on automatiseeritud.

Määratud iteratsiooni ehk for-tsükli kasutamise näiteid¶

In [17]:
a = 'Python'
for letter in a:  # NB! operaator in pakib lahti.
    print(letter, end=' ')
P y t h o n 
In [18]:
lst = [6, 5, 4]
for i in lst:
    print(i)
6
5
4
In [19]:
tpl = (6, 5, 4)
for i in tpl:
    print(i)
6
5
4
In [20]:
dictionary = {'foo': 1, 'bar': 2, 'baz': 3}
for k in dictionary:  # Vaikimisi väljastab võtmed.
    print(k)
foo
bar
baz
In [21]:
for k in dictionary:
    print(dictionary[k])
1
2
3
In [22]:
for key, value in dictionary.items():  # Operaator in ja lahtipakkimine.
    print(key, ':', value)
foo : 1
bar : 2
baz : 3
In [23]:
for k in dictionary:
    print(k, ':', dictionary[k])
foo : 1
bar : 2
baz : 3
In [24]:
s = {6, 5, 4}
for i in s:
    print(i)  # Hulk pole järjestatud.
4
5
6

Sisseehitatud funktsiooni enumerate tutvustus:

In [25]:
lst = ['Liisa', 'Juulius', 'Mari']
print(list(enumerate(lst)))
[(0, 'Liisa'), (1, 'Juulius'), (2, 'Mari')]
In [26]:
for i, item in [(0, 'Liisa'), (1, 'Juulius')]:  # Operaator in ja lahtipakkimine.
    print(i, '-->', item)
0 --> Liisa
1 --> Juulius
In [27]:
for i, item in enumerate(lst):
    print(i, '-->', item)
0 --> Liisa
1 --> Juulius
2 --> Mari

Näide: Omista indeksid listis olevatele nimedele. Praktikas tihti esinev probleem.

Pikem lahendus:

In [28]:
sõbrad = ['Mari', 'Mai', 'Olev']

index = 0
for nimi in sõbrad:
    print(index, nimi)
    index += 1
0 Mari
1 Mai
2 Olev

Lühem lahendus mis kasutab for-tsüklit ja funktsiooni enumerate:

In [29]:
for index, nimi in enumerate(sõbrad):
    print(index, nimi)
0 Mari
1 Mai
2 Olev

Sisseehitatud vahemikku defineeriva funktsiooni range kasutamise näited:

In [30]:
for i in range(3):  # Genereerib tulemuse iga iteratsiooni alguses.
    print(i)
0
1
2
In [31]:
for i in range(2, 17, 5):  # range([<algus>,] <lõpp>, [<samm>])
    print(i)
2
7
12

Näide: Arvu iteratiivne astendamine.

In [32]:
def astenda(arv, aste):
    tulem = 1
    for _ in range(aste):  # Kui tead, et ei kasuta muutujat _ või _i.
        tulem *= arv
    return tulem

astenda(2, 3)
Out[32]:
8

for-break konstruktsioon¶

Sarnaselt while-tsüklile peatab lausend break itereerimisprotsessi täielikult ja murrab protsessi tsüklist välja. Joonis 9 kujutab for-break konstruktsiooni voodiagrammi.

No description has been provided for this image
Joonis 9: for-tsüklis oleva for-break konstruktsiooni voodiagramm. Kriipjoonega tähistatud tegevused on automatiseeritud.
In [33]:
for n in [1, 2, 3, 4]:
    if n == 3:
        break
    print(n)
1
2

Näide: Pangaautomaat versioon 3.

In [34]:
raha_masinas = 3
raha_soov = int(input('Kui palju raha tahad?'))

for raha in range(1, raha_soov + 1):
    if raha > raha_masinas:
        print('Masinas sai raha otsa. Vabandame.')
        break
    print('1 euro')

print('Head aega.')
1 euro
1 euro
1 euro
Masinas sai raha otsa. Vabandame.
Head aega.

for-continue konstruktsioon¶

Lausend continue töötab samal viisil nagu while-tsüklis. Lausend continue peatab hetkel teostatavat iteratsiooni ja alustab järgmise iteratsiooni tsükliga. Joonis 10 kujutab for-continue konstruktsiooni voodiagrammi.

No description has been provided for this image
Joonis 10: for-tsüklis oleva for-continue konstruktsiooni voodiagramm. Kriipjoonega tähistatud tegevused on automatiseeritud.
In [35]:
for n in [1, 2, 3, 4]:
    if n == 3:
        continue
    print('Juulius on eksamil põrunud', n, 'korda.')
Juulius on eksamil põrunud 1 korda.
Juulius on eksamil põrunud 2 korda.
Juulius on eksamil põrunud 4 korda.

Näite: Lausendite continue ja break kasutamine ühes tsüklis.

In [36]:
for i in range(10):
    if i <= 3:
        continue
    elif i > 6:
        break
    print(i)
4
5
6

for-else konstruktsioon¶

Lausend else käitumine on sama mis while-tsüklis. Tegevus mis kaasneb lausendiga else teostatakse juhul kui kõik while-tsükli iteratsioonid on teostatud (tsükkel on ammendunud), st., et lausend break pole tsüklit enneaegselt lõpetanud. Joonised 11 ja 12 kujutavad for-else konstruktsiooni voodiagramme juhul kui tsüklis ei esine lausendit break ja kui see esineb.

No description has been provided for this image
Joonis 11: for-tsüklis oleva for-else konstruktsiooni voodiagramm. Kriipjoonega tähistatud tegevused on automatiseeritud.
In [37]:
for n in [1, 2]:
    print(n)
else:
    print('Tsükkel ammendus.')
1
2
Tsükkel ammendus.
No description has been provided for this image
Joonis 12: for-tsüklis oleva for-break-else konstruktsiooni voodiagramm. Kriipjoonega tähistatud tegevused on automatiseeritud.
In [38]:
for n in [1, 2, 3, 4]:
    print(n)
    if n == 3:
        break  # Lõpetan tsükli enneaegselt.
else:
    print('Tsükkel ammendus? Ei.')
1
2
3

Näide: Leia etteantud loendist esimene viiega jaguv arv, prindi see. Kui loendis puudub viiega jaguv arv prindi sellekohane teade (ainult üks kord) kasutades ühte for-tsüklit.

Vale lahendus võrdluseks:

In [39]:
numbrid = [1, 2, 3]
for number in numbrid:
    if number % 5 == 0:
        print(number)
        break
    else:
        print('[Vale] Arvu ei leitud.')  # Vale, prindib mitu korda.
[Vale] Arvu ei leitud.
[Vale] Arvu ei leitud.
[Vale] Arvu ei leitud.

Õige lahendus:

In [40]:
for number in numbrid:
    if number % 5 == 0:
        print(number)
        break
else:
    print('[Õige] Arvu ei leitud.')
[Õige] Arvu ei leitud.

Näide: Pangaautomaat versioon 4.

In [41]:
raha_masinas = 3
raha_soov = int(input('Kui palju raha tahad?'))

for raha in range(1, raha_soov + 1):
    if raha > raha_masinas:
        print('Masinas sai raha otsa. Vabandame.')
        break
    print('1 euro')
else:
    print('Head aega.')  # Pole ilus mõnitada.
1 euro
1 euro
1 euro
Masinas sai raha otsa. Vabandame.

Pesastatud for-tsükkel¶

for-tsükleid on võimalik üksteise sisse pesastada. Joonis 13 kujutab for-tsüklisse pesastatud for-tsükli voodiagrammi.

No description has been provided for this image
Joonis 13: for-tsüklisse pesastatud for-tsükkel. Kriipjoonega tähistatud tegevused on automatiseeritud. Pesastatud tsükkel on tähistatud rohelise ristkülikuga.
In [42]:
for i in range(2):
    for j in range(3):
        print('i =', i,'\tj =', j)
i = 0 	j = 0
i = 0 	j = 1
i = 0 	j = 2
i = 1 	j = 0
i = 1 	j = 1
i = 1 	j = 2
In [43]:
mat = [
    [1, 2, 3],
    [4, 5, 6],
    [7, 8, 9],
    [0]
]

for rida in mat:  # Prindime read.
    print(rida)
    
for rida in mat:
    for veerg in rida:    
        print(veerg, end=' ')  # Veergudes ja ridades olevad arvud.
[1, 2, 3]
[4, 5, 6]
[7, 8, 9]
[0]
1 2 3 4 5 6 7 8 9 0 

Näide: Nädal ja nädalapäevade tunnid 2.

In [44]:
päevad = ['E', 'L', 'P']
päeva_pikkus = 2  # Tundides.

for päev in päevad:
    print(päev)
    for tund in range(päeva_pikkus + 1):
        print(f'kell on {tund}.')

print('\nUus nädal.')
E
kell on 0.
kell on 1.
kell on 2.
L
kell on 0.
kell on 1.
kell on 2.
P
kell on 0.
kell on 1.
kell on 2.

Uus nädal.

Näide: Algarvude otsimine.

In [45]:
n_max = 11
for n in range(2, n_max + 1):
    for x in range(2, n):
        if n % x == 0:
            print(f'    {n} = {x} * {n // x}')
            break  # Väljub pesastavasse tsüklisse.
    else:
        print('Arv', n, 'on ALGARV!')
Arv 2 on ALGARV!
Arv 3 on ALGARV!
    4 = 2 * 2
Arv 5 on ALGARV!
    6 = 2 * 3
Arv 7 on ALGARV!
    8 = 2 * 4
    9 = 3 * 3
    10 = 2 * 5
Arv 11 on ALGARV!

















☻   ☻   ☻