Black Friday je tu! Využij jedinečnou příležitost a získej až 80 % znalostí navíc zdarma! Více zde
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í.
BF extended 2022

Lekce 10 - Funkce a výjimky v Pythonu

V předešlém cvičení, Řešené úlohy k 8. a 9. lekci Pythonu, jsme si procvičili nabyté zkušenosti z předchozích lekcí.

V tomto tutoriálu 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é řešíme samostatně. Jednotlivé podproblémy řeší funkce. Pro funkcionální styl programování můžeme použít vše, co jsme se naučili doposud.

Funkce obvykle přijímá argumenty (data, která zpracuje) a něco vrací - nějakou výslednou hodnotu apod. (ale taky nemusí 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ů. Funkce může být i bez argumentů. Při volání funkce se do nich dosazují hodnoty 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:

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 např:

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

Argumentů jsou dva druhy - 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 mají dánu výchozí hodnotu a nemusí být při volání funkce zadány v tom pořadí, v jakém jsou deklarovány. Navíc je nemusíme při volání funkce inicializovat (určit jejich hodnotu), v tom případě se použije je základní hodnota.

Syntaxe: název_argumentu=hodnota

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

Nyní příklad - vylepšená verze 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) nebo mocnina(1, exponent=2), a dostaneme stejný výsledek. Navíc třeba můžeme umocnit 3 na 4 - mocnina(3, exponent=4).

Operátor *

Můžeme použít i operátor *. Ten nám umožní dělat zajímavější věci.

Např.:

nejaka_funkce(*pozicni_argumenty)

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

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 projíždět cyklem for..in.

Chceme-li to samé pro klíčové argumenty napíšeme dvě hvězdičky.

Příklad:

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

Pro zájemce - můžeme použít chuťovku typu:

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

Přičemž nám funkce nedovolí použít poziční argumenty.

Rekurze

Rekurze označuje když funkce volá sama sebe. Lze ji použít například na výpočet faktoriálu.

Příklad:

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

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

print()

Jak jsem kdysi slíbil, tak se naučíme upravit si funkci print(). Nyní se podíváme na její dva klíčové argumenty:

  • sep - mezery mezi jednotlivými prvky (pozičními argumenty) - normálně nastaveno na mezeru (" ")
  • end - čím se zápis ukončí - normálně znak nového řádku ("\n")

Příklady:

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

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

Ošetření chyb

Ve většině programů, co jsme dosud vytvořili, byla chyba při vstupu čísla. Pokud jsme zadali místo čísla např. písmeno, tak program spadl.

Nyní si 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 napsat:

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 ve zdrojovém kódu
  • ZeroDivisionError - dělení nulou
  • TypeError - nesprávné použití datových typů - např. sčítání řetězce a čísla apod.
  • ValueError - nesprávná hodnota

Více výjimek zde (AJ): https://docs.python.org/…eptions.html

A nyní si ještě jednou vylepšíme naši kalkulačku:

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 libovolnou klávesu...")

Nejprve vyrobíme funkci na získání čísla ze vstupu od uživatele:

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 opakuje v cyklu, dokud nezadáme správný vstup. Řádek s float() převede řetězec na desetinné číslo.

Dále vyrobíme funkci na vstup "y" nebo "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

Skoro to samé...

Další na řadě je volba:

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!")

A ošetření dělení nulou. Šlo by i jen kontrolovat, zdali je druhé číslo 0.

A nyní hlavní cyklus:

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 libovolnou klávesu...")
main()

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

V příští lekci, Vícerozměrná pole v Pythonu, se podíváme na dvourozměrná 2D pole a vícerozměrná pole obecně, včetně příkladů a polí "zubatých".


 

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 1102x (1.96 kB)
Aplikace je včetně zdrojových kódů v jazyce Python

 

Předchozí článek
Řešené úlohy k 8. a 9. lekci Pythonu
Všechny články v sekci
Základní konstrukce jazyka Python
Přeskočit článek
(nedoporučujeme)
Vícerozměrná pole v Pythonu
Článek pro vás napsal gcx11
Avatar
Uživatelské hodnocení:
186 hlasů
(^_^)
Aktivity

 

 

Komentáře
Zobrazit starší komentáře (50)

Avatar
Jozef
Člen
Avatar
Jozef:4. října 11:21

Chyba je v odsadeni: riadok 5.
return nemoze byt sucastou cyklu (zastavi ho pri prvej hodnote)

 
Odpovědět
4. října 11:21
Avatar
Petra Sluková :19. října 15:16

Souhlasím. I já mám bohužel s každou další lekcí v kurzu svízelnější pocit, že už vlastně nic nechápu a jsem na to sama. Taky dohledávám jinde. Nechci to vzdát, chci se to pořádně naučit, proto jsem také tady, ale začínám být zoufalá. Kdyby třeba k lekcím byla alespoň videa... Poradí mi prosím někdo, kdo se ocitl v té samé fázi, jak se z toho dostat ven? Co mu třeba pomohlo? Předem díky.

 
Odpovědět
19. října 15:16
Avatar
Odpovídá na Petra Sluková
Roman Staněk:22. října 21:31

Ahoj, je to úplně normální :) myslím, že si tím prošel každý, ovšem každý v jiné fázi. Já osobně jsem měl tento pocit při OOP při lekcích s arénou. Nechápal jsem proč se co dělá. Na týden jsem učení přerušil a během toho týdne, když jsem na to občas myslel a přemýšlel o tom, mi to najednou začalo dávat smysl. Tak jsem si zpětně prošel lekce a najednou, jako bych to viděl z jiného pohledu. Myslím, že je důležité si přenastavit myšlení a nehltat kapitoly jednu po druhé, ale klidně si tu kapitolu přečíst několikrát a co je asi nejdůležitější, probranou látku si hned zkusit. Experimentovat s kódem a kombinovat to s předchozími lekcemi.
Pardon za obsáhlejší odpověď, nechal jsem se unést, jelikož jsou mi tvé pocity velmi blízké.

 
Odpovědět
22. října 21:31
Avatar
Odpovídá na Roman Staněk
Petra Sluková :23. října 8:29

Ahoj Romane, moc děkuju za podporu a rady. Snad mi to brzy taky naskočí. Zkusím tvoje metody. :-)

 
Odpovědět
23. října 8:29
Avatar
František Hronek:4. listopadu 18:30

v programu kalkulačky mi chybí vysvětlení hlavního cyklu, tedy jestli hlavní cyklus startuje celou sekvenci a nebo ne a jestli je na konec definice main() potřeba vždy znovu použít funkci main() a jestli je main() "kouzelné slovíčko a nebo ho mohu nahradit třeba definicí def program(): a ukončit program(). Jinak super práce a moc děkuju.

 
Odpovědět
4. listopadu 18:30
Avatar
Radka
Člen
Avatar
Odpovídá na Petra Sluková
Radka:23. listopadu 19:50

Najdi si videa Davida Šetka....mně neuvěřitelně pomohl. Pokud něco nechápeš, odpovídá ještě ten de. Zpravidla v noci. Je skvělý.

Odpovědět
23. listopadu 19:50
Nikdy neříkej nikdy
Avatar
Odpovídá na Radka
Petra Sluková :24. listopadu 9:03

Ahoj Radko, děkuju Ti za odpověď. A naprosto s Tebou souhlasím, já se podle něj učím taky. :-) Jen opravdu úžasný. To je právě ale to, co mě mrzí. Kdykoliv se vrátím sem a jdu v lekcích dál, padá na mě zase úzkost. :-) Jenže jsem tu v kurzu a potřebuji ho dokončit. No, snad se mi to povede..

 
Odpovědět
24. listopadu 9:03
Avatar
Radka
Člen
Avatar
Odpovídá na Petra Sluková
Radka:24. listopadu 12:40

neboj se...dáš to...já mám zítra zkoušky a taky jsem ještě před pár týdny nevěřila, že se k nim dostanu

Odpovědět
24. listopadu 12:40
Nikdy neříkej nikdy
Avatar
Odpovídá na Radka
Petra Sluková :24. listopadu 13:55

Páni, jsi dobrá. Tak držím palce, ať Ti to dobře dopadne. :-)

 
Odpovědět
24. listopadu 13:55
Avatar
Radka
Člen
Avatar
Odpovídá na Petra Sluková
Radka:24. listopadu 14:02

nevím , jestli jsem dobrá...ale projekt jsem zvládla, toho jsem se bála
jsi na Discordu? Ať tu neplevelíme

Odpovědět
24. listopadu 14:02
Nikdy neříkej nikdy
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 10 zpráv z 60. Zobrazit vše