Nauč se Python > Kurzy > Začátečnický kurz Pyladies > Funkce a řetězce > Vlastní funkce

Funkce

Dříve jsme volaly funkce, které napsal někdo jiný:

print('Ahoj světe!')

Dnes si ukážeme, jak psát funkce vlastní.

Není to tak složité:

def obvod_obdelnika(sirka, vyska):
    "Vrátí obvod obdélníka daných rozměrů"
    return 2 * (sirka + vyska)

print(obvod_obdelnika(4, 2))

Jak to funguje?

Funkce se definuje příkazem def, za nějž napíšeš jméno funkce, pak do závorky seznam argumentů, které funkce bere, a pak dvojtečku.

Potom následuje odsazené tělo funkce – příkazy, které funkce provádí. Tělo může začít dokumentačním řetězcem, který popisuje, co funkce dělá.

Příkazem return pak můžeš z funkce vrátit nějakou hodnotu.

Tělo funkce může mít více příkazů, včetně podmínek, cyklů a podobně:

def napis_hlasku(nazev, skore):
    "Popíše skóre. Název má být přivlastňovací přídavné jméno."

    print(nazev, 'skóre je', str(skore))
    if skore > 1000:
        print('Světový rekord!')
    elif skore > 100:
        print('Skvělé!')
    elif skore > 10:
        print('Ucházející.')
    elif skore > 1:
        print('Aspoň něco')
    else:
        print('Snad příště.')

napis_hlasku('Tvoje', 256)
napis_hlasku('Protivníkovo', 5)

Při volání funkce se hodnoty, se kterými funkci zavoláš, přiřadí jednotlivým argumentům. Takže když zavoláš třeba napis_hlasku('Tvoje', 256), můžeš si představit, že funkce dělá následující:

nazev = 'Tvoje'
skore = 256

print(nazev, 'skóre je', str(skore))
if skore > 1000:
    ... # atd.

Vracení

Speciální příkaz return, který jde použít jenom ve funkcích, ukončí funkci a vrátí danou hodnotu ven z funkce.

Chová se tedy trochu jako break, jen místo cyklu opouští celou funkci.

def ano_nebo_ne(otazka):
    "Vrátí True nebo False, podle odpovědi uživatele"
    while True:
        odpoved = input(otazka)
        if odpoved == 'ano':
            return True
        elif odpoved == 'ne':
            return False
        else:
            print('Nerozumím! Odpověz "ano" nebo "ne".')

if ano_nebo_ne('Chceš si zahrát hru? '):
    print('OK! Ale napřed si ji musíš naprogramovat.')
else:
    print('Škoda.')

Stejně jako if nebo break je return příkaz, ne funkce. Kolem „své“ hodnoty nepotřebuje závorky.

Zkus napsat funkci, která vrátí obsah elipsy daných rozměrů. Příslušný vzoreček je A = πab, kde a a b jsou délky os.

Funkci zavolej a výsledek vypiš.

Řešení

Vrátit nebo vypsat?

Předchozí program se dá napsat i takto:

from math import pi

def obsah_elipsy(a, b):
    print('Obsah je', pi * a * b)

obsah_elipsy(3, 5)

Program takhle funguje, ale přichází o jednu z hlavních výhod funkcí: možnost vrácenou hodnotu použít i jinak jež jen v print.

Funkci, která výsledek vrací, můžeš použít v dalších výpočtech:

def obsah_eliptickeho_valce(a, b, vyska):
    return obsah_elipsy(a, b) * vyska

print(obsah_eliptickeho_valce(3, 5, 3))

... ale kdyby výsledek přímo vypsala, nešlo by to.

None

Když funkce neskončí příkazem return, automaticky se vrátí hodnota None.

Je to hodnota zabudovaná přímo do Pythonu, podobně jako True nebo False, a znamená „nic“.

def nic():
    "Tahle funkce nic nedělá"

print(nic())

Lokální proměnné

Gratuluji, umíš definovat vlastní funkce! Zbývá ještě vysvětlit jednu věc: lokální a globální proměnné.

Funkce může používat proměnné „zvnějšku“:

pi = 3.1415926

def obsah_kruhu(polomer):
    return pi * polomer ** 2

print(obsah_kruhu(100))

Ale všechny argumenty a všechny proměnné, do kterých funkce přiřazuje, jsou úplně nové proměnné, které nemají nic společného s tím, co je „venku“ kolem funkce.

Těm úplně novým proměnným se říká lokální proměnné (angl. local variables), protože existují jen místně, v rámci volání jedné jediné funkce. Takže tohle nebude fungovat tak, jak se zdá:

x = 0

def nastav_x(hodnota):
    x = hodnota  # Přiřazení do lokální proměnné!

nastav_x(40)
print(x)

Proměnné, které nejsou lokální, jsou globální – ty existují v celém programu. (Jen ve funkcích, které mají náhodou lokální proměnnou stejného jména, „nejsou vidět“ – to jméno označuje lokální proměnnou.)

Pojďme si to ukázat. Než spustíš tenhle program, zkus předpovědět, co bude dělat. Pak ho pusť, a pokud dělal něco jiného, zkus vysvětlit proč. Pozor, je tam chyták!

from math import pi
obsah = 0
a = 30

def obsah_elipsy(a, b):
    obsah = pi * a * b  # Přiřazení do `obsah`
    a = a + 3  # Přiřazení do `a`
    return obsah

print(obsah_elipsy(a, 20))
print(obsah)
print(a)

A tady jsou f:

Řešení

Jestli ti to celé připadá zmatené a složité, dá se tomu zatím vyhnout dodržováním jednoho pravidla: nepřiřazuj ve funkcích do proměnných, které existují i vně funkce. (Parametr funkce se počítá jako přiřazení.)