7. Vytvárame podprogramy

V tejto časti sa naučíme vytvárať a potom aj používať nové vlastné príkazy. Pripomeňme si najprv, aké príkazy už poznáme:

  • priraďovací príkaz vytvorí novú premennú, resp. zmení zapamätanú hodnotu premennej

  • print vypíše do textového okna nejaké texty a číselné hodnoty (aj hodnoty premenných)

  • platno = tkinter.Canvas() vytvorí plátno grafickej aplikácie

  • platno.pack() zobrazí plátno v grafickej aplikácii

  • platno.create_rectangle do plátna nakreslí obdĺžnik

Už sme použili aj import tkinter - príkaz, ktorý sme zatiaľ nevysvetľovali. Stačí si pamätať, že vďaka tomuto zápisu môžeme v Pythone pracovať s grafikou tkinter.

Zrejme príkazy platno = tkinter.Canvas() a platno.pack() použijeme len raz na začiatku programu a ďalej sa budú volať aj veľakrát ostatné príkazy.

Vlastné príkazy

Z existujúcich príkazov môžeme vytvárať vlastné nové príkazy. Špeciálnym spôsobom označíme postupnosť príkazov (tzv. blok), ktorá bude vykonávať náš nový príkaz a tejto postupnosti priradíme meno, ktoré sa stane novým príkazom. Budeme hovoriť, že podprogram je pomenovaný blok príkazov.

Definovanie nového príkazu (teda podprogramu) zapisujeme takto:

def meno_príkazu():
    príkaz
    príkaz
    ...

Ukážme to na príklade, v ktorom nový podprogram bude vedieť vypísať nejaký dopredu daný text:

def vypis_text():
    print('************')
    print('** Python **')
    print('************')

Týmto zápisom sme zadefinovali nový príkaz vypis_text, ktorý je od tohto momentu pripravený na vykonanie. Samotné definovanie nového príkazu (podprogramu) ešte nič z postupnosti príkazov nevykonáva. Budeme hovoriť, že definícia podporgramu sa skladá z hlavičky - to je prvý riadok definície def vypis_text(): a z tela - blok príkazov, v ktorom je každý riadok odsunutý o 4 medzery vpravo. Túto definíciu si zjednodušene môžeme predstaviť ako vytvorenie novej premennej s menom vypis_text, ktorej hodnotou je telo, teda blok príkazov:

_images/07_01.png

Môžeme sa o tom presvedčiť tak, že sa pokúsime zistiť hodnotu premennej vypis_text:

>>> vypis_text
<function vypis_text at 0x0306C348>

Python nám namiesto hodnoty tejto premennej oznámil, že meno vypis_text je funkcia. Takto pythonisti volajú nové príkazy, teda podprogramy. Ak chceme, aby sa tento náš nový príkaz vykonal, musíme ho zavolať. Volanie podprogramu sa robí tak, že k jeho menu prilepíme okrúhle zátvorky:

meno_príkazu()

Vyskúšame to s našim novým príkazom:

>>> vypis_text()
************
** Python **
************
>>>

Vidíme, že sa postupne vykonali všetky tri príkazy z tela podprogramu a keď už urobil všetko čo mal, vypísali sa znaky >>>, ktorými nám Python oznamuje, že je pripravený na ďalšie príkazy. Všimnite si chybovú správu, ktorú dostaneme, keď sa preklepneme v mene príkazu:

>>> vypys()
...
NameError: name 'vypys' is not defined

Podprogram s menom vypys sa nedá zavolať, lebo do neho nebolo ešte nič priradené, nexistuje takáto premenná, v pamäti nemá priradenú hodnotu. Ak teraz zapíšeme napr.

>>> vypys = 123
>>> vypys()
...
TypeError: 'int' object is not callable

Chybová správa sa zmenila: premenná je už definovaná a keďže je to celé číslo (v Pythone int), tak toto sa nedá zavolať (callable) ako podprogram.

Vráťme sa k nášmu novému príkazu vypis_text. Už sme ho raz zavolali a vtedy vypísal tie tri riadky textu. Lenže my ho môžeme zavolať ľubovoľný počet krát a kým nemeníme definíciu podprogramu, bude stále robiť to isté, teda vypisovať tieto tri riadky. Otestujme to programom:

# program definuje a zavola podprogram

def vypis_text():
    print('************')
    print('** Python **')
    print('************')

print('Vitajte!')
vypis_text()
print()
vypis_text()
print('to je koniec')

V tomto programe sa najprv definuje podprogram vypis_text, potom sa budú pomocou print vypisovať nejaké texty a medzi tým sa dvakrát zavolá definovaný podprogram vypis_text. Spustíme a dostávame:

Vitajte!
************
** Python **
************

************
** Python **
************
to je koniec

Všimnite si, že volanie príkazu print bez parametrov, teda print(), označuje vypísanie prázdneho riadka.

Je dôležité si zapamätať, že podprogram môžeme zavolať až vtedy, keď už bol definovaný predtým. Ak by sme vyskúšali opraviť náš program:

# program definuje a zavola podprogram

print('Vitajte!')
vypis_text()

def vypis_text():
    print('************')
    print('** Python **')
    print('************')

Dozvieme sa, že v 4. riadku programu sme použili meno vypis_text(), ktoré ešte nebolo definované:

Vitajte!
Traceback (most recent call last):
  File "podprogram.py", line 4, in <module>
    vypis_text()
NameError: name 'vypis_text' is not defined
>>>

Vlastné príkazy s grafikou

Zatiaľ poznáme jediný grafický príkaz create_rectangle na kreslenie obdĺžnikov. Zostavme pomocou neho štyri podprogramy, pomocou ktorých nakreslíme jednoduchého robota:

  • nový príkaz hlava nakreslí na správnom mieste dva obdĺžniky: pre krk a hlavu

  • telo nakreslí veľký obdĺžnik pre telo

  • ruky nakreslí dva úzke obdĺžniky pre dve ruky, prípadne ich spojíme do jedného, aby sa obe ruky nakreslili naraz

  • nohy nakreslí dva úzke obdĺžniky pre dve nohy

Pozrite takéto použitie podprogramov:

# program nakresli robota

import tkinter

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

def hlava():
    platno.create_rectangle(160, 40, 200, 100, fill='sky blue')
    platno.create_rectangle(150, 10, 210, 55, fill='steel blue')

def telo():
    platno.create_rectangle(140, 70, 220, 190, fill='royal blue')

def ruky():
    platno.create_rectangle(80, 90, 280, 110, fill='tomato')

def nohy():
    platno.create_rectangle(150, 160, 170, 250, fill='purple')
    platno.create_rectangle(190, 160, 210, 250, fill='purple')

hlava()
ruky()
nohy()
telo()

Dostaneme takúto kresbu:

_images/07_02.png

Keď vymeníme záverečné poradie volaní týchto podprogramov:

telo()
ruky()
hlava()
nohy()

dostaneme trochu iný obrázok:

_images/07_03.png

Úlohy

  1. V 3. časti ste vytvárali program, ktorý vypísal, napr. takúto vašu vizitku:

    +--------------------+
    |             ~~~    |
    |  Juraj    / o o \  |
    |  JÁNOŠÍK  \  ~  /  |
    |             """    |
    |    IT konzultant   |
    +--------------------+
    

    Napíšte podprogram vizitka, ktorý vie vypísať takúto vizitku. Keď tento podprogram zavoláme napr. 10-krát za sebou, dostávame vypísaných 10 vizitiek.

  1. Napíšte podporgram domcek, ktorý pomocou znakov hviezdička vypíše napr. takýto domček:

       *
      * *
     *   *
    *******
    **   **
    * * * *
    *  *  *
    * * * *
    **   **
    *******
    

    Volaním tohto podprogramu vypíšte pod seba 5 domčekov.

  1. Napíšte podprogram slovensky_kriz, ktorý nakreslí dvojkríž zo Slovenského štátneho znaku pomocou troch obdĺžnikov. Napr.

    _images/07_04.png

Zhrnutie

čo sme sa naučili:

  • podprogramy slúžia zoskupenie nejakej postupnosti príkazov, takéto podprogramy môžeme potom volať pomocou ich mena aj viackrát

  • podprogramy umožňujú rozdeliť riešenie väčšej úlohy na menšie časti, pričom každú časť rieši nejaký podprogram - takéto riešenia môžu byť prehľadnejšie a lepšie čitateľné