11. Program s opakovaním

Tento program paťkrát vypisuje tú istú dvojicu riadkov:

print('Programujem v Pythone')
print('=====================')
print('Programujem v Pythone')
print('=====================')
print('Programujem v Pythone')
print('=====================')
print('Programujem v Pythone')
print('=====================')
print('Programujem v Pythone')
print('=====================')

Pripomeňme program, ktorý päťkrát zavolá podprogram a ten kreslí štvorček na náhodnú pozíciu:

import tkinter
import random

platno = tkinter.Canvas(bg='white')
platno.pack()

def stvorec_nahodne():
    x = random.randint(10, 310)
    y = random.randint(10, 200)
    platno.create_rectangle(x, y, x+50, y+50, fill='indian red')

stvorec_nahodne()
stvorec_nahodne()
stvorec_nahodne()
stvorec_nahodne()
stvorec_nahodne()

V oboch predchádzajúcich príkladoch sa opakuje vykonávanie jedného alebo viacerých príkazov. V programovaní je veľmi bežné, že sa nejaké výpočty, výpisy alebo kreslenia útvarov opakujú viackrát za sebou. Ak sa to opakuje málokrát, napr. len dvakrát alebo trikrát, nie je problém, tú istú časť skopírovať viackrát za sebou. Iná situácia je, keď sa niečo opakujeveľmi veľakrát, pripadne počet opakovaní závisí od nejakej premennej. Programátori dobre vedia, že na tieto situácie sa v každom programovacom jazyku nachádza príkaz opakovania.

Príkaz opakovania s daným počtom opakovaní

Naučíme sa nový príkaz v Pythone, ktorý umožní opakovať nejakú časť programu (tzv. blok príkazov) viackrát. Tento príkaz má takáto tvar:

for premenná in range(počet):
    príkaz
    príkaz
    ...

Aj v tejto programovej konštrukcii, podobne ako pri definovaní nového príkazu, odsunutý blok príkazov určuje čo sa bude opakovať (opäť riadky bloku odsúvame o 4 znaky vpravo) a v hlavičke cyklu sa udáva, ktorá premenná sa pri tom použije ako tzv. počítadlo cyklu. V tomto počítadle, teda premennej cyklu Python nastavuje (počítaz), koľko krát sa už cyklus doteraz vykonal. Výraz range(počet) určuje rozsah číselných hodnôt, pre ktorý bude tento cyklus bežať.

Najlepšie to ukážeme na predchádzajúcich príkladoch, ktoré prepíšeme s použitím tzv. for-cyklu.

Prvá ukážka

V prvok príklade sa päťkrát za sebou opakuje táto dvojica príkazov:

print('Programujem v Pythone')
print('=====================')

Keď tieto dva príkazy vložíme ako telo cyklu a opakovanie (teda range) nastavíme na 5, dostaneme:

for i in range(5):
    print('Programujem v Pythone')
    print('=====================')

Program teraz vypíše týchto 10 riadkov:

Programujem v Pythone
=====================
Programujem v Pythone
=====================
Programujem v Pythone
=====================
Programujem v Pythone
=====================
Programujem v Pythone
=====================

Python tu opakoval celý blok príkazov (tzv. telo cyklu) päťkrát. Premennú cyklu sme tu nazvali menom i. Programátori veľmi často (keď nemajú fantáziu) nazývajú premennú cyklu písmenami ´´i´´ alebo j alebo k. Neskôr uvidíme aj iné názvy pre premenné cyklu.

Uvedomte si, že blok príkazov končí vtedy, keď nasleduje príkaz, ktorý už nie je odsunutý. Zmeňme predchádzajúci program:

for i in range(5):
    print('Programujem v Pythone')
print('=====================')

V tomto prípade telo cyklu obsahuje jediný riadok - príkaz print('Programujem v Pythone') a riadok s príkazom print('=====================') je už mimo cyklu. Tento program päťkrát zopakuje jediný riadok vypisu a na záver vypíše riadok so znakmi rovná sa:

Programujem v Pythone
Programujem v Pythone
Programujem v Pythone
Programujem v Pythone
Programujem v Pythone
=====================

Druhá ukážka

V druhom programe sa najprv definoval podprogram stvorec_nahodne a potom sa tento podprogram zavolal päťkrát. Aj v tomto príklade päť volaní stvorec_nahodne() nahradíme for-cyklom:

import tkinter
import random

platno = tkinter.Canvas(bg='white')
platno.pack()

def stvorec_nahodne():
    x = random.randint(10, 310)
    y = random.randint(10, 200)
    platno.create_rectangle(x, y, x+50, y+50, fill='indian red')

for i in range(100):
    stvorec_nahodne()

Všimnite si, že sme päť zavolaní podprogramu nahradili číslo 100. Program nakreslí 100 malých farebných štvorčekov na náhodné pozície. Dostaneme:

_images/11_01.png

Keby sme nepoznali for-cyklus, bol by tento program veľmi dlhý: asi by sme 100-krát pod seba zapisovali volanie stvorec_nahodne().

Premenná cyklu

Táto premenná pri každom prechode cyklu postupne nadobúda číselné hodnoty z rozsahu, ktorý je daný hodnotou počet.

Otestujeme to týmto krátkym programom:

print('zaciatok')
for i in range(4):
    print(i, 'test')
print('koniec')

Tento program najprv vypíše reťazec zaciatok, potom vo for-cykle niekoľko krát jeden print s premennou i a na záver po skončení cyklu reťazec koniec:

zaciatok
0 test
1 test
2 test
3 test
koniec

Na tomto príklade vidíme, že príkaz print(i, 'test') sa vykonal presne štyrikrát a pri každom prechode cyklu premenná (počítadlo) i postupne nadobudla hodnoty 0, 1, 2, 3, teda sú to postupne všetky čísla od 0 až do počet-1. Tento program by sme mohli prepísať bez cyklu takto:

print('zaciatok')
i = 0
print(i, 'test')
i = 1
print(i, 'test')
i = 2
print(i, 'test')
i = 3
print(i, 'test')
print('koniec')

Zrejme by sme po spustení dostali rovnaký výsledok, ako verzia s for-cyklom. Vidíme, že zápis range(4) označuje postupnosť hodnôt pre premennú cyklu i, ktorá začína 0 a končí o jedna menším číslom ako 4.

Pozrime tento ďalší príklad:

cislo = 0
for i in range(5):
    cislo = cislo + i * i
print('vysledok =', cislo)

Vidíme, že v cykle sa nebude nič vypisovať, ale bude sa päťkrát priraďovať do tej istej premennej. Aj tejto for-cyklus vieme rozpísať na niekoľko príkazov bez použitia cyklu:

cislo = 0
i = 0
cislo = cislo + i * i
i = 1
cislo = cislo + i * i
i = 2
cislo = cislo + i * i
i = 3
cislo = cislo + i * i
i = 4
cislo = cislo + i * i
print('vysledok =', cislo)

Pozorne pozrime na jeden z priraďovacích príkazov, napr.

cislo = cislo + i * i

Ak by to bola matematická rovnica, tak to pre konkrétne i nedáva veľký zmysel (napr. cislo = cislo + 1). Lenže v tomto prípade to označuje príkaz priradenia: najprv sa vypočíta hodnota výrazu na pravej strane za =, teda cislo + i * i a až potom sa táto hodnota priradí do premennej cislo. Tým sa zmení pôvodná hodnota tejto premennej. Poďme tento program postupne odkrokovať (niekedy hovoríme aj trasovať): ku každému riadku programu pripíšeme obsahy premenných a výrazov:

Ttrasovacia tabuľka

príkaz

cislo

i

i*i

výpis

cislo = 0

0

i = 0

0

0

cislo = cislo + i * i

0

i = 1

1

1

cislo = cislo + i * i

1

i = 2

2

4

cislo = cislo + i * i

5

i = 3

3

9

cislo = cislo + i * i

14

i = 4

4

16

cislo = cislo + i * i

30

print('vysledok =', cislo)

vysledok = 30

Vidíme, že priraďovací príkaz cislo = cislo + hodnota pripočíta danú hodnotu k doterajšiemu obsahu premennej cislo. Budeme hovoriť, že toto priradenie zvyšuje hodnotu danej premennej (inkrementuje). Z trasovacej tabuľky si môžeme dovoliť povedať, že daný program počíta súčty druhých mocnín čísel od 0 do 4.

Úlohy

  1. Zistite, aký výsledok dostaneme pre:

    cislo = 0
    for i in range(11):
        cislo = cislo + i * i
    print('vysledok =', cislo)
    
  2. Program z predchádzajúcej úlohy počíta cislo = 0*0 + 1*1 + 2*2 + 3*3 + 4*4 + ... + 10*10. Ako dlho by vám to trvalo,keby ste to počítali ručne, prípadne s použitím obyčajnej kalkulačky?

  1. Ako treba opraviť tento program, aby počítal súčty druhých mocním až do 100? Opravte program a zistite výsledok.

Zhrnutie

čo sme sa naučili:

  • pomocou príkazu for môžeme opakovať vykonávanie jedného alebo viacerých príkazov (tzv. blok príkazov)

  • všetky riadky bloku príkazov musia byť odsunuté o 4 medzery vpravo

  • for-cyklus používa premennú cyklu, ktorá pri každom prechode postupne nadobúda hodnoty s udanej postupnosti pomocou range

dôležité zásady:

  • meno premennej cyklu zvoľte tak, aby čo najlepšie vyjadrovalo hodnotu, ktorá sa v cykle bude automaticky meniť