Hledáme nové posily do ITnetwork týmu. Podívej se na volné pozice a přidej se do nejagilnější firmy na trhu - Více informací.
Pouze tento týden sleva až 80 % na e-learning týkající se Java. Zároveň využij akce až 80 % zdarma při nákupu e-learningu. Více informací:

Lekce 11 - Funkce a výjimky v Pythonu

V minulé lekci, Textové řetězce v Pythonu do třetice - Split a Join, jsme si uvedli metodu Split() na textových řetězcích.

V tomto tutoriálu základů programování v jazyku Python se naučíme používat funkce a funkcionální styl programování. Dále se naučíme jednoduché ošetřování chyb programu. Vylepšíme si naši kalkulačku a uděláme z ní první chybám odolný program.

Funkce

Doteď jsme programy psali imperativně - proveď tento příkaz, potom tamten atd. Tímto způsobem lze psát jednoduché a krátké programy. Větší programy by však byly velmi nepřehledné. Proto přejdeme na další programovací paradigma (způsob jak něco naprogramovat) - funkcionální styl programování. Náš program si rozdělíme na menší části (podproblémy), které vyřešíme samostatně. Jednotlivé podproblémy řeší funkce. Pro funkcionální styl programování můžeme použít vše, co jsme se doposud naučili.

Funkce obvykle přijímá argumenty (data, která zpracuje) a něco vrací, například nějakou výslednou hodnotu. Nemusí ale také vracet nic - jako např. funkce print().

Základní syntaxe funkce

Funkce mají syntaxi podobnou větvícím příkazům (if, elif, else). Funkce se definuje pomocí klíčového slova def a výslednou hodnotu vrací klíčovým slovem return. Za def se píše mezera a poté název funkce. Za název funkce se dávají jednoduché závorky, do kterých se píší názvy jednotlivých argumentů. Při volání funkce se do nich dosazují hodnoty argumentů. Funkce může být i bez argumentů. Na konci prvního řádku se píše dvojtečka. Tělo funkce se standardně odsazuje.

Příklad:

def mocnina(cislo):
    cislo = cislo ** 2
    return cislo

Takto vytvořená funkce mocnina vrací číslo umocněné na druhou. Například při zavolání mocnina(1) vrátí 1, při zavolání mocnina(2) vrátí 4 atd. V praxi to vypadá takto:

def mocnina(cislo):
    cislo = cislo ** 2
    return cislo
prvni_cislo = mocnina(2)
print(prvni_cislo)

Argumentů samozřejmě může být i více:

def soucin(prvni_cislo, druhe_cislo, treti_cislo):
    cislo = prvni_cislo * druhe_cislo * treti_cislo
    return cislo
priklad = soucin(2, 3, 4)
print(priklad)

Argumenty

V Pythonu máme dva druhy argumentů - poziční a klíčové.

Poziční argumenty jsme viděli výše. Na jejich pozici se dosadí argument na stejné pozici při volání funkce. Tyto argumenty nemají dánu základní hodnotu.

Syntaxe: název_argumentu

Klíčové argumenty mají již předem nastavenou hodnotu, kterou lze změnit. Na rozdíl od argumentů pozičních jsou označeny klíčovým slovem (mají svůj název). Tyto argumenty nemusí být při volání funkce zadány v pořadí, v jakém jsou deklarovány. Navíc je nemusíme při volání funkce inicializovat (určit jejich hodnotu). V takovém případě se použije jejich základní hodnota.

Syntaxe: název_argumentu=hodnota

Všechny poziční argumenty musí být deklarovány před klíčovými!

Jako příklad si ukažme vylepšenou verzi funkce mocnina:

def mocnina(cislo, exponent=2):
    cislo = cislo ** exponent
    return cislo

První argument je poziční, druhý je klíčový. Nyní můžeme volat mocnina(1), mocnina(1, exponent=2), případně mocnina(1, 2) a dostaneme stejný výsledek. Navíc třeba můžeme umocnit 3 na 4 - mocnina(3, exponent=4).

Obecně se poziční argumenty zapisují jako args a klíčové jako kwargs.

Operátor *

Můžeme použít také operátor *. Ten nám umožní dělat zajímavější věci. Podívejme se na následující příklad:

nejaka_funkce(*pozicni_argumenty)

Díky tomuto zápisu se všechny zadané poziční argumenty vloží do n-tice (něco jako seznam) s názvem pozicni_argumenty. Tu poté můžeme například procházet cyklem for. Opět si ukažme příklad:

def soucin(*cisla):
    vysledek = 1
    for cislo in cisla:
        vysledek = vysledek * cislo
    return vysledek
priklad = soucin(2, 3, 4, 5)
print(priklad)

Můžeme dokonce zapsat i chuťovku typu:

funkce(*, prvni_klicovy_arg=1, druhy_klicovy_arg=1)

V tomto případě nám funkce nedovolí použít poziční argumenty

Chceme-li použít zápis s operátorem * pro klíčové argumenty, napíšeme dvě hvězdičky.

Rekurze

Pojem rekurze označuje zápis kódu, kdy funkce volá sama sebe. Rekurzi můžeme použít například na výpočet faktoriálu. Uveďme si příklad:

def faktorial(cislo):
    if cislo > 0:
        return faktorial(cislo - 1) * cislo
    else:
        return 1

Při rekurzi si musíme dát pozor, aby se funkce někdy ukončila. Jinak program upadne na přetečení zásobníku. Rekurze podrobně vysvětlujeme u algoritmu faktoriálu.

print()

Nyní se naučíme upravit si funkci print(). Nejprve se podíváme na její dva klíčové argumenty:

  • sep - argument udává mezery mezi jednotlivými prvky (pozičními argumenty) - normálně je nastavený na mezeru (" "),
  • end - tento argument definuje, čím se zápis ukončí - normálně se tak děje znakem nového řádku ("\n").

Příklady:

print(1, 2, 3, "a", sep="-")

print("Žádná nová řádka", end=" ")
print("nebude.", end=" ")

Ošetření chyb

Ve většině námi dosud vytvořených programů jsme uživateli umožnili spáchat chybu při číselném vstupu . Pokud by tedy uživatel zadal - a on v praxi zadá :-) - místo čísla např. písmeno, náš program by spadl.

Nyní si tedy ukážeme, jak takovéto chyby ošetřit. Ošetření se provádí pomocí bloku try-except.

Syntaxe:

try:
    #blok příkazů
except jmeno_prvni_vyjimky:
    #blok příkazů
except jmeno_dalsi_vyjimky:
    #blok příkazů
#zde je buď konec, nebo zachycení dalších výjimek

Pokud chceme zachytit i chybovou zprávu, musíme kód upravit takto:

except jmeno_vyjimky as chyba:
    #text vyjímky se uloží do proměnné chyba

Chybám se v Pythonu (a v objektových jazycích obecně) říká výjimky. Ty základní jsou následující:

  • SyntaxError - chyba je ve zdrojovém kódu,
  • ZeroDivisionError - pokus o dělení nulou,
  • TypeError - nesprávné použití datových typů - např. sčítání řetězce a čísla,
  • ValueError - nesprávná hodnota.

Více výjimek můžeme nastudovat v dokumentaci Pythonu.

Vylepšení kalkulačky

Teď máme dost znalostí na to, abychom znovu vylepšili naši kalkulačku. Nejprve si připomeňme její dosavadní kód:

print("Kalkulačka\n")
pokracovat = True
while pokracovat:
    prvni_cislo = int(input("Zadejte první číslo: "))
    druhe_cislo = int(input("Zadejte druhé číslo: "))
    print("1 - sčítání")
    print("2 - odčítání")
    print("3 - násobení")
    print("4 - dělení")
    print("5 - umocňování")
    cislo_operace = int(input("Zadejte číslo operace: "))
    if cislo_operace == 1:
        print("Jejich součet je:", prvni_cislo + druhe_cislo)
    elif cislo_operace == 2:
        print("Jejich rozdíl je:", prvni_cislo - druhe_cislo)
    elif cislo_operace == 3:
        print("Jejich součin je:", prvni_cislo * druhe_cislo)
    elif cislo_operace == 4:
        print("Jejich podíl je:", prvni_cislo / druhe_cislo)
    elif cislo_operace == 5:
        print(prvni_cislo, "na", druhe_cislo, "je:", prvni_cislo ** druhe_cislo)
    else:
        print("Neplatná volba!")
    nezadano = True
    while nezadano:
        odpoved = input("\nPřejete si zadat další příklad? y / n: ")
        if (odpoved == "y" or odpoved == "Y"):
            nezadano = False
        elif (odpoved == "n" or odpoved == "n"):
            nezadano = False
            pokracovat = False
        else:
            pass
input("\nStiskněte klávesu Enter...")

Nejprve vyrobíme uživateli-vzdornou :-) funkci na získání čísla ze vstupu:

def nacti_cislo(text_zadani, text_chyba):
    spatne = True
    while spatne:
        try:
            cislo = float(input(text_zadani))
            spatne = False
        except ValueError:
            print(text_chyba)
        else:
            return cislo

Program se tak dlouho opakuje v cyklu, dokud od uživatele nezískáme správný vstup. Řádek s float() převede řetězec na desetinné číslo.

Dále si vyrobíme funkci, která umožní zadat pouze znaky y, Y, n a N:

def dalsi_priklad():
    nezadano = True
    while nezadano:
        odpoved = input("\nPřejete si zadat další příklad? y / n: ")
        if (odpoved == "y" or odpoved == "Y"):
            return True
        elif (odpoved == "n" or odpoved == "N"):
            return False
        else:
            pass

Příkaz pass sám o sobě nedělá nic. Umožní nám ale pokračování cyklu bez zobrazení chyby.

Dále musíme ošetřit, co se stane po volbě operace. Uživatel by mohl zadat například čísla 5 a 0 a poté zvolit dělení. Náš program by pak skončil s výjimkou ZeroDivisionError. Musíme se tedy o tuto potenciální chybu postarat:

def volba(prvni_cislo, druhe_cislo):
    print("1 - sčítání")
    print("2 - odčítání")
    print("3 - násobení")
    print("4 - dělení")
    print("5 - umocňování")
    cislo_operace = nacti_cislo("Zadej volbu: ", "Neplatné zadání!\n")
    if cislo_operace == 1:
        print("Jejich součet je:", prvni_cislo + druhe_cislo)
    elif cislo_operace == 2:
        print("Jejich rozdíl je:", prvni_cislo - druhe_cislo)
    elif cislo_operace == 3:
        print("Jejich součin je:", prvni_cislo * druhe_cislo)
    elif cislo_operace == 4:
        mezivysledek = 0
        try:
            mezivysledek = prvni_cislo / druhe_cislo
            print("Jejich podíl je:", mezivysledek)
        except ZeroDivisionError:
            print("Dělení nulou!")
    elif cislo_operace == 5:
        print(prvni_cislo, "na", druhe_cislo, "je:", prvni_cislo ** druhe_cislo)
    else:
        print("Neplatná volba!")

Hlavní cyklus programu se s našimi novými funkcemi značně zjednoduší:

def main():
    print("Kalkulačka\n")
    pokracovat = True
    while pokracovat:
        prvni_cislo = nacti_cislo("Zadej číslo: ", "Neplatné číslo!\n")
        druhe_cislo = nacti_cislo("Zadej číslo: ", "Neplatné číslo!\n")
        volba(prvni_cislo, druhe_cislo)
        if dalsi_priklad():
            pass
        else:
            pokracovat = False
    input("\nStiskněte klávesu Enter...")
main()

Dosáhli jsme toho, že jsme celý kód rozdělili do přehledných a jednoduchých bloků. Případné úpravy či hledání chyby v kódu pak budou výrazně jednodušší. Celý kód je také daleko lépe čitelný. Toto je podstata funkcionálního paradigmatu!

Kompletní kód kalkulačky je k dispozici níže ke stažení.

V příští lekci, Knihovny math a random, se podíváme na matematické funkce.


 

Měl jsi s čímkoli problém? Stáhni si vzorovou aplikaci níže a porovnej ji se svým projektem, chybu tak snadno najdeš.

Stáhnout

Stažením následujícího souboru souhlasíš s licenčními podmínkami

Staženo 1184x (1.16 kB)
Aplikace je včetně zdrojových kódů v jazyce Python

 

Předchozí článek
Textové řetězce v Pythonu do třetice - Split a Join
Všechny články v sekci
Základní konstrukce jazyka Python
Přeskočit článek
(nedoporučujeme)
Knihovny math a random
Článek pro vás napsal gcx11
Avatar
Uživatelské hodnocení:
243 hlasů
(^_^)
Aktivity