Počítač za mě řeší nudné úkoly
- Sdružovat související příkazy do tzv. funkcí namísto jejich zdlouhavého vypisování jednotlivě.
- Pomocí parametrů umožnit použít už jednou napsanou funkci k řešení mnoha podobných úkolů.
Po chvíli počítání v konzoli a neustálého vyhledávání v historii příkazůKlávesami ↑ a ↓ možná dojdeš k tomu, že je to trochu otrava. „Vzorečky“ se opakují pořád dokola, mění se jen hodnoty. Člověk při tom snadno udělá chybu. Tím spíš, když výpočet vyžaduje více příkazů za sebou. Lepší by bylo znovu zadávat jen to, co se opravdu mění.
Je čas prozkoumat, k čemu slouží levá polovina stránky s interaktivní konzolí: Do ní můžeš vepsat delší posloupnosti příkazů (tzv. zdrojový kód programu), které pak najednou jediným tlačítkem (► v pravém horním rohu plochy s kódem) spustíš. Hodí se to třeba právě na delší výpočty.
Příklad: Obsah trojúhelníku jednodušeji
Zkus následující zdrojový kód vložit na příslušné místo a spustit!
import math
a = 64
b = 87
c = 68
PulObvodu = (a+b+c)/2
Obsah = math.sqrt( PulObvodu * (PulObvodu - a) * (PulObvodu - b) * (PulObvodu - c) )
print(Obsah)
Tlačítko run vezme obsah okna vlevo, a vloží ho celý najednou do konzole vpravo podobně, jako kdybychom ho tam vepsali ručně. Rozdíl je v tom, že nebudou automaticky vypsány výsledky všech výpočtů — nejspíš by jich totiž bylo prostě příliš mnoho. Výsledky je proto lepší lepší ukládat do příslušných proměnných (beztak je nejspíš budeme chtít znovu použít).
Co všechno v předchozím zdrojovém kódu je třeba změnit, když chceš vypočítat obsah jiného trojúhelníku? Svou odpověď ověř!
Co myslíš, že dělá řádek print(Obsah)?
Řešení
K výpočtu na základě jiných hodnot stačí tyto hodnoty upravit ve zdrojovém kódu vlevo a celý program znovu spustit příslušným tlačítkem.
Řádek print(Obsah) vytiskne obsah proměnné Obsah.
Funkce
Psaní delších posloupností příkazů je pokrok, my ale půjdeme ještě dál. Obvykle totiž nepotřebujeme opakovaně spouštět přesně stejný stejný zdrojový kód, zároveň ale nechceme pokaždé vše přepisovat. Často chceme provádět stejnou činnost, ale s různými vstupními daty.
Vyzkoušej zadat (do levé části) následující kód a spustit:
import math
def ObsahTrojuhelniku(a, b, c):
PulObvodu = (a+b+c)/2
Obsah = math.sqrt(PulObvodu * (PulObvodu - a) * (PulObvodu - b) * (PulObvodu - c))
return Obsah
Zdrojový kód funkce se vykonává při každém zavolání. Modul ale stačí načíst jednou, pak už je můžeme bez obav používat (dokud Python třeba nerestartujeme). Proto je import modulu mimo definici funkce.
Nic se nestalo? Ale ano. Po stisku tlačítka (►) Python opravdu vykonal zadaný zdrojový kód. V něm funkci ObsahTrojuhelniku definujemePřesně popisujeme, jak se funkce jmenuje, s jakými pracuje daty a co s nimi přesně dělá. — ale nespouštíme! Tak se ani nic nevypsalo. Po provedení kódu s definicí funkce už ale Python ví, jak obsah trojúhelníka počítat. Můžeš to vyzkoušet v konzoli (tmavá plocha vpravo). Zadej do ní postupně třeba:
ObsahTrojuhelniku(46, 78, 86)
ObsahTrojuhelniku(64, 87, 68)
ObsahTrojuhelniku(3, 4, 5)
ObsahTrojuhelniku(1, 1, math.sqrt(2))
Co se tady přesně odehrává? Funkci vyvoláme zadáním jejího jména spolu s potřebnými parametry, např. ObsahTrojuhelniku(46, 78, 86). Asi nepřekvapí, co to znamená: žádáme tím Python, aby vykonal funkci ObsahTrojuhelniku s hodnotami 46, 78 a 86. Python opět neudělá nic překvapivého. Označí zadané hodnoty jmény parametrů z definice funkce (a, b a c) a začne s vykonáváním funkce podle zadaného zdrojového kódu, řádek po řádku, jako kdyby šlo o běžný program. Když je hotovo, vrátí řízení zpět konzoli, tedy nám, a my můžeme zadat další příkaz.
Přemýšlej: jak souvisí funkce v matematice a v programování? Co mají společného, čím se liší?
Funkce (neboli podprogramy) tedy slouží k tomu, abychom nemuseli znovu a znovu a znovu zadávat tentýž zdrojový kód. Již vytvořené funkce lze opakovaně spouštět s různými vstupními daty. Díky nim nemusíme vše programovat „od základů“ jen se základními operacemi. Stejně tak přirozeně používáme šroubováky, kleště či acetylenové hořáky a jsem rádi, že si je nemusíme pokaždé znovu vyrábět pomocí pěstního klínu.
Funkce důvěrně znáš z tabulkového procesoru.
Definice funkce
Velikost odsazení je na uvážení programátora. Obvykle jsou to 2-4 mezery nebo jeden tabulátor (Tab). Výhoda je, že odsazení tabulátorem lze jednoduše vrátit kombinací Shift+Tab (je to stejné jako víceúrovňové seznamy v textových procesorech). Protože Python používá odsazení k rozpoznání těla funkce (nebo jiných struktur, se kterými se ještě seznámíme), je důležité, aby bylo odsazení řádků, které tvoří společný blok, vždy stejné.
Podíváme se teď podrobněji, jak vlastně definice funkce vypadá. Klíčové slovo def značí, že bude následovat definice funkce. Dál následuje jméno vznikající funkce (ObsahTrojuhelniku), v závorce její parametry (pojmenování proměnných, se kterými bude pracovat, tedy a, b a c) a dvojtečka (:), za níž následuje tzv. tělo funkce — tedy to, co funkce opravdu dělá. Všechny následující odsazené řádky jsou součástí těla funkce. Vidíme, že funkce použije parametry k výpočtu poloviny obvodu a následně spočte obsah zadaného trojúhelníku. Ten je výsledkem práce funkce, proto je tzv. vrácen pomocí klíčového slova return. To běh funkce zároveň ukončí.
Vzájemné volání funkcí
Další výhodou funkcí je možnost jejich vzájemného volání v rámci většího programu. Zatím se zde zabýváme ukázkovými příklady, ale asi už si dovedeš představit, že se delší programy mohou snadno stát nepřehlednými. Funkce umožňují program rozdělit na menší činnosti. Když je pak na nějakém místě programu potřeba vykonat činnost, kterou už jsme jednou naprogramovali, není třeba kopírovat zdrojový kód. Stačí zavolat onu funkci.
Příklad: Objem hranolu
Jak počítáme objem hranolu s trojúhelníkovou podstavou? Vynásobíme obsah té podstavy výškou hranolu. Těžší část úkolu je patrně spočítat tu plochu podstavy. Ovšem pro trojúhelníkovou podstavu už to umíme! Zdrojový kód pro výpočet objemu hranolu (s trojúhelníkovou podstavou) tedy může vypadat takto:
def ObjemHranolu(Strana1, Strana2, Strana3, Vyska):
ObsahZakladny = ObsahTrojuhelniku(Strana1, Strana2, Strana3)
Objem = ObsahZakladny * Vyska
return Objem
Doplň funkci na výpočet objemu hranolu za funkci na výpočet obsahu trojúhelníka, celý zdrojový kód znovu přelož a v interaktivní konzoli prozkoušej.
Zdrojový kód funkce ObjemHranolu je srozumitelnější, protože se nezaobírá tím, jak přesně se spočte obsah základny. Prostě zavolá už existující funkci a použije vrácenou hodnotu. Teď už si dovedeš lépe představit, jak to probíhá ve velkém programu, třeba ve webovém prohlížeči. Poměrně obecné funkce řeší, co se stane např. při kliknutí na nějaké místo na stránce. Provedení funkce spočívá ve volání jednodušších (základnějších) funkcí, které volají ještě základnější funkce, až nakonec procesor „jenom“ přesouvá nuly a jedničky. Díky tomu se v programech dá vyznat.
Dosud známe dva způsoby, jakými může funkce komunikovat s vnějším světem: return (vrácení hodnoty) a print() (tisk textu na obrazovku). Z jejich fungování je také jasné, kdy je který způsob vhodnější: když chceme něco sdělit uživateli, použijeme print(). Pokud chceme s výsledkem funkce dále pracovat v samotném programu, použijeme return. Je to patrné i na této ukázce: kdyby byl výsledek funkce ObsahTrojuhelniku jen vytištěn na obrazovku a nikoliv vrácen, nešlo by jej použít v dalším výpočtu.
S mnoha funkcemi v jednom programu se snadno stane, že dvě různé funkce používají proměnnou se stejným názvem. Aby v tom byl pořádek nedocházelo ke konfliktům, pracuje s nimi Python jako s různými proměnnými. Z jedné funkce tedy nelze přistupovat k proměnným druhé funkce, ani když se jmenují stejně. Různé funkce totiž často zpracovávají různí lidé a ti nemusí vůbec tušit, s jakými názvy proměnných pracují jejich kolegové.
Skutečný systém tzv. viditelnosti proměnných je o něco složitější, takže z uvedeného pravidla existují výjimky. Pro začátek nám ale tohle stačí: každá funkce pracuje s vlastními proměnnými. Ke komunikaci s vnějším světem slouží předávání parametrů (vstup funkce) a vracení výsledků (výstup funkce).
Příklady
Samozřejmě využij, co znáš z dřívějška!
- Promysli si, jak budeš postupovat:
- Připomeň si, co je BMI.
- Ujasni si, které informace jsou k výpočtu potřeba — ẗo budou parametry (vstupy) funkce.
- Připomeň si, jak se BMI počítá. To bude muset být obsaženo v těle funkce.
- Po této základní přípravě začni psát:
- Chceš definovat funkci. Takže potřebuješ klíčové slovo def, název funkce, v závorce určit parametry a dvojtečkou naznačit, že následuje odsazené tělo funkce.
- Do těla funkce zapiš samotný postup výpočtu: Do známého vzorce (vyjádřeného v Pythonu) dosaď příslušné parametry.
- Nezapomeň výsledek výpočtu vrátit pomocí klíčového slova return
- Když máš hotový zdrojový kód, nezapomeň ho otestovat (a případně opravit).
Řešení
Jedno z možných řešení:
def BMI(Vaha, Vyska) :
return Vaha/(Vyska**2)
Klíčové slovo return může vracet nejen hodnotu proměnné, ale také výsledek výpočtu, což jsme zde využili.
Shrnutí
- Chceme-li několikrát opakovat stejnou činnost, vyplatí se utvořit pro ni funkci (pomocí klíčového slova def).
- Funkce reprezentuje celou posloupnost příkazů, které můžeme spustit zavoláním funkce.
- Funkci můžeme předávat různá data ke zpracování ve formě parametrů.
- Chytře navržené funkce zkracují a zpřehledňují zdrojový kód, čímž nám šetří práci.
- Chytře navržené funkce také umožňují soustředit se na jednotlivé části většího úkolu postupně, čímž usnadňují jeho řešení.