Cvičení č. 7 rozšířené o poznámky ze cvičení a řešení některých příkladů (ZS 2026/27)¶

V minulém díle jste viděli...¶

Podmíněný příkaz if s volitelnými bloky elif a else:

In [1]:
a = 0
if a > 0:
    print("číslo je kladné")
elif a == 0:
    print("číslo se rovná 0")
else:
    print("číslo není kladné")
číslo se rovná 0

Podmíněný výraz:

In [2]:
x = -1
y = 2
z = x if x + y > 0 else y

Příkaz while:

In [3]:
n = 0
while n <= 4:
    print(n)
    n += 1
0
1
2
3
4

Příkazy break a continue sloužící pro podrobnější kontrolu provádění cyklů.

Příkaz for využívající funkci range jako zdroj hodnot:

In [4]:
for n in range(10, 0, -3):
    print(n)
10
7
4
1
In [7]:
for n in range(5):
    print(n)
0
1
2
3
4

Strukturování programu: funkce¶

Funkce jsou patrně nejdůležitější prvek programovacích jazyků, který slouží ke strukturování programu. Umožňují totiž pojmenovat určitou skupinu příkazů, které potom lze použít opakovaně s různými vstupními parametry. Pokud tedy programujeme algoritmus pro řešení nějaké úlohy, můžeme jej umístit do samostatné funkce, abychom při opakovaném řešení úlohy s jinými daty nemuseli znovu programovat ten samý algoritmus. Funkce tedy programátorům umožňují dodržovat princip don't repeat yourself (DRY).

In [8]:
# již známe 2 druhy funkcí: funkce, co mají nějaké parametry a vrací hodnotu 
# a funkci print pro vypisování
x = -3
y = abs(x)
y
Out[8]:
3
In [10]:
y = print("ahoj")
ahoj
In [12]:
print(y)
None

Příkaz def – definice funkce¶

Příkaz def je složený příkaz, který se skládá z hlavičky a těla funkce. Hlavička se skládá z klíčového slova def, názvu funkce, seznamu parametrů uvnitř kulatých závorek a závěrečné dvojtečky. Tělo funkce následující za dvojtečkou tvoří blok příkazů se správným odsazením dle univerzálního syntaktického pravidla.

Zápis se nejlépe vysvětlí pomocí příkladů. Následující funkce print_demo nemá žádný parametr:

In [4]:
# definice funkce: hlavička a tělo
# Tato funkce nemá žádný parametr a vrací hodnotu None
def print_demo():
    print("Byla spuštěna funkce 'print_demo'.")

Funkce print_demo1 má jeden parametr:

In [2]:
# definice funkce s jedním parametrem
def print_demo1(param):
    print("Hodnota parametru je", param)

Funkce print_demo2 má dva parametry:

In [3]:
# definice funkce se dvěma parametry
def print_demo2(param1, param2):
    print("Hodnota prvního parametru je", param1)
    print("Hodnota druhého parametru je", param2)

print_demo2(2, 3)
Hodnota prvního parametru je 2
Hodnota druhého parametru je 3

Všimněte si, že při spuštění příkazu def nedošlo ke spuštění příkazů v těle dané funkce. Při definici funkce dojde pouze k vytvoření objektu, který reprezentuje danou funkci a obsahuje kód definovaný v těle funkce. Odkaz na tento objekt se uloží do proměnné s názvem dané funkce.

In [3]:
# příkaz definice funkce je podobný jako příkaz definice proměnné: 
# také nic nevypíše, ale vytvoří se objekt reprezentující funkci a proměnná 
# (zde print_demo), která na objekt odkazuje
# mrkněte na proměnné v debbugeru
x = 7
In [5]:
# výpis hodnoty, na kterou odkazuje proměnná 'x': číslo
print(x)
7
<function print_demo at 0x7f2dd4703740>

Výpis samotného objektu reprezentujícího funkci vypadá takto:

In [ ]:
# výpis hodnoty, na kterou odkazuje proměnná 'print_demo':
# objekt, který reprezentuje funkci
print(print_demo)
In [6]:
# volání (spuštění) funkce (už známe):
print_demo()
Byla spuštěna funkce 'print_demo'.
In [5]:
# Volání funkce s jedním parametrem, "ahoj" je argument pro parametr 'param'
print_demo1("ahoj")
print_demo1(12)
Hodnota parametru je ahoj
Hodnota parametru je 12

Pokud chceme funkci použít, musíme ji zavolat pomocí kulatých závorek, přičemž musíme předat správný počet argumentů odpovídající definici funkce, jinak dojde k chybě:

In [9]:
print_demo()        # zde nepředáváme žádný argument
print_demo1(10)     # číslo 10 je argument pro parametr 'param'
print_demo2(10, 20) # čísla 10 je argument pro parametr 'param1', 20 je argument pro parametr 'param2'
Byla spuštěna funkce 'print_demo'.
Hodnota parametru je 10
Hodnota prvního parametru je 10
Hodnota druhého parametru je 20
In [10]:
# funkci musíme volat se správným počtem argumentů
print_demo1(10, 5)
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Cell In[10], line 1
----> 1 print_demo1(10, 5)

TypeError: print_demo1() takes 1 positional argument but 2 were given
In [11]:
# funkci musíme volat se správným počtem argumentů
print_demo1()
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Cell In[11], line 1
----> 1 print_demo1()

TypeError: print_demo1() missing 1 required positional argument: 'param'

Syntaxe příkazu def má mnoho různých variant, které souvisí zejména s definicí seznamu parametrů funkce. Zatím se jimi nebudeme zabývat a postupně se k tomuto tématu budeme vracet.

Příklad¶

Napište funkci say_hello(name), která vypíše pozdrav pro uživatele se zadaným jménem. (Anglicky, abychom nemuseli skloňovat...). Funkci několikrát zavolejte, vyzkoušejte různé hodnoty argumentu.

In [8]:
def say_hello(name):
    print("Hello", name)

say_hello("Jane")
say_hello("Tom")

for i in range(5):
    say_hello(i)
Hello Jane
Hello Tom
Hello 0
Hello 1
Hello 2
Hello 3
Hello 4

Příkaz return – vrácení výsledku funkce¶

V matematice se pojmem funkce označuje předpis, který ze vstupní hodnoty (případně vstupních hodnot) počítá nějakou výstupní hodnotu. Předchozí příklady funkcí print_demo atd. nemají žádný výsledek. K vrácení výsledné hodnoty zevnitř funkce na místo, kde byla funkce zavolána, slouží příkaz return. Volání funkce je výraz, může tedy vystupovat např. napravo od přiřazovacího operátoru:

In [9]:
# K vrácení výsledné (návratové) hodnoty funkce slouží příkaz return:
def polynom(x):
    return x ** 2 - 3 * x + 1

vysledek = polynom(2.5)
print(vysledek)
-0.25
In [14]:
# před příkazem return může být složitější výpočet:
def polynom(x):
    y = x ** 2 - 3 * x
    y += 1
    return y 

# výslednou (návratovou) hodnotu funkce mohu např. vložit do proměnné:
vysledek = polynom(2.5)
print(vysledek)

# nebo rovnou vypsat:
print(polynom(2.5))

# ukázka: debugger + pytutor
-0.25
-0.25
In [12]:
# volání funkcí může být součástí složitějších výrazů
vysledek = polynom(2.5) + 3 * abs(polynom(3)) - 4 
print(vysledek)
-1.25

Příkazem return končí vykonávání dané funkce a žádné další příkazy z těla funkce se nevykonají. To je důležité zejména pokud funkce obsahuje příkazy return uvnitř podmínek nebo cyklů. Pokud funkce neobsahuje žádný příkaz return nebo pokud dojde k vykonání prázdného příkazu return (tj. ukončení funkce bez vrácení hodnoty), je výsledkem funkce hodnota None:

In [15]:
# příkaz return okamžitě ukončí funkci (jako break u cyklu)
def polynom(x):
    y = x ** 2 - 3 * x
    return
    y += 1
    return y 

vysledek = polynom(2.5)
print(vysledek)
None
In [19]:
def polynom(x):
    if x < 0:
        print("Definiční obor této funkce nezahrnuje záporná čísla.")
        return
    return x ** 2 - 3 * x + 1

vysledek = polynom(10)
print("Výsledek je", vysledek)
Výsledek je 71
In [18]:
# pokud funkce neobsahuje za příkazem return hodnotu, je její návratovou hodnotou None:
vysledek = polynom(-1)
print("Výsledek je", vysledek)
Definiční obor této funkce nezahrnuje záporná čísla.
Výsledek je None
In [22]:
# ukázka signum: další příklad použití příkazu return v různých větvích výpočtu:
def signum(x):
    if x > 0:
        return 1
    if x < 0:
        return -1
    return 0

# Ukázka: pokud chci otestovat funkci, obvykle ji zavolám opakovaně pro různé vstupy
# a zkontroluji výsledek (není třeba volat input())
print(signum(10), signum(1.5), signum(0), signum(-0.5), signum(-10))
1 1 0 -1 -1
In [25]:
# pokud funkce neobsahuje příkaz return, je její návratovou hodnotou None:
def say_hello(name):
    print("Hello", name)

x = say_hello("Anna")
print("Výsledek je", x)
Hello Anna
Výsledek je None

Příklad¶

  1. Napište funkci je_sudé(n), která vrací True nebo False podle toho, jestli je zadané přirozené číslo n sudé nebo není. Funkci zavolejte.
In [23]:
def je_sude(n):
    if n % 2 == 1:
        return False
    else:
        return True
        
print(je_sude(56))
print(je_sude(5))
print(je_sude(0))
True
False
True
In [25]:
def je_sude(n):
    return n % 2 == 0
        
print(je_sude(56))
print(je_sude(5))
print(je_sude(0))
True
False
True
In [26]:
def je_sude(n):
    return not n % 2 
        
print(je_sude(56))
print(je_sude(5))
print(je_sude(0))
True
False
True
  1. Analogicky napište funkci je_liché(n). Využijte při tom předchozí funkci. Funkci zavolejte.
In [28]:
def je_liche(n):
    if je_sude(n):
        return False
    else:
        return True
        
print(je_liche(56))
print(je_liche(5))
print(je_liche(0))
False
True
False
In [29]:
def je_liche(n):
    return not je_sude(n)
        
print(je_liche(56))
print(je_liche(5))
print(je_liche(0))
False
True
False

Proměnné a obor platnosti¶

Lokální proměnná je proměnná, která je definovaná uvnitř funkce. Jakmile skončí vykonávání dané funkce, zaniknou i všechny lokální proměnné definované uvnitř dané funkce.

Uvnitř funkce máme naopak přístup objektům s širším oborem platnosti, jako jsou např. globální proměnné, ale i globálně importované moduly, jiné funkce definované na stejné úrovni, apod. Názvy definované na vyšší úrovni ale můžeme pouze použít, nemůžeme je změnit – viz následující příklad:

In [39]:
# původní příklad
# globální proměnná
globalni = 10

def f():
    # lokální proměnná
    lokalni = 1

    # použití globální proměnné
    lokalni += globalni

    # uvnitř funkce nelze měnit globální proměnné
    #globalni += 1

    # výpis lokálních proměnných
    print("lokalni", lokalni)

# použití funkce
f()

# výpis globálních proměnných
print("globalni", globalni)

# lokální proměnné definované uvnitř funkce nejsou k dispozici na globální úrovni
#print(lokalni)
lokalni 11
globalni 10
In [27]:
# Proměnné dělíme na globální (definované na úrovni programu) 
# a lokální (definované na úrovni funkce)

# globální proměnná
globalni = 10

def f():
    # lokální proměnná
    lokalni = 1
    lokalni += 3

    # výpis lokálních proměnných
    print("lokalni", lokalni)

# použití funkce
f()

# výpis globálních proměnných
print("globalni", globalni)

# ukázka pytutor
lokalni 4
globalni 10
globalni 10
In [30]:
# Parametry funkce jsou také lokální proměnné

# globální proměnná
globalni = 10

# parametry funkce jsou také lok. proměnné
def f(parametr):
    # lokální proměnná
    lokalni = 1
    lokalni += parametr
    parametr *= 10

    # výpis lokálních proměnných
    print("lokalni", lokalni, parametr)

# použití funkce
f(globalni)

# výpis globálních proměnných
print("globalni", globalni)
lokalni 11 100
globalni 10
In [31]:
# lokální proměnná žije jen uvnitř funkce, když funkce skončí, zanikne:

# globální proměnná
globalni = 10

# parametry funkce jsou také lok. proměnné
def f(parametr):
    # lokální proměnná
    lokalni = 1
    lokalni += parametr
    parametr *= 10

    # výpis lokálních proměnných
    print("lokalni", lokalni, parametr)

# použití funkce
f(globalni)

# výpis globálních proměnných
print("globalni", globalni)

# lokální proměnné definované uvnitř funkce nejsou k dispozici na globální úrovni
print(lokalni)
lokalni 11 100
globalni 10
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[31], line 23
     19 # výpis globálních proměnných
     20 print("globalni", globalni)
     21 
     22 # lokální proměnné definované uvnitř funkce nejsou k dispozici na globální úrovni
---> 23 print(lokalni)

NameError: name 'lokalni' is not defined
In [33]:
# Globální proměnné mohu uvnitř funkce
# používat, ale nemohu je tam měnit

# globální proměnná
globalni = 10

def f():
    # lokální proměnná
    lokalni = 1

    # použití globální proměnné
    lokalni += globalni

    # uvnitř funkce nelze měnit globální proměnné
    # globalni += 1

    # výpis lokálních proměnných
    print("lokalni", lokalni)

    # výpis globálních proměnných
    print("globalni", globalni)
# použití funkce
f()

# výpis globálních proměnných
print("globalni", globalni)

# lokální proměnné definované uvnitř funkce nejsou k dispozici na globální úrovni
# print(lokalni)
lokalni 11
globalni 10
globalni 10
In [36]:
# Uvnitř funkce nelze měnit globální proměnné
# tj. jakmile uvnitř funkce použiju globální proměnnou, již nesmím definovat
# lokální proměnnou stejného jména:

# globální proměnná
globalni = 10

def f():
    # lokální proměnná
    lokalni = 1

    # použití globální proměnné
    lokalni += globalni

    # uvnitř funkce nelze měnit globální proměnné
    globalni += 1

    # výpis lokálních proměnných
    print("lokalni", lokalni)

# použití funkce
f()

# výpis globálních proměnných
print("globalni", globalni)

# lokální proměnné definované uvnitř funkce nejsou k dispozici na globální úrovni
# print(lokalni)
---------------------------------------------------------------------------
UnboundLocalError                         Traceback (most recent call last)
Cell In[36], line 19
     15     # výpis lokálních proměnných
     16     print("lokalni", lokalni)
     17 
     18 # použití funkce
---> 19 f()
     20 
     21 # výpis globálních proměnných
     22 print("globalni", globalni)

Cell In[36], line 10, in f()
      6     # lokální proměnná
      7     lokalni = 1
      8 
      9     # použití globální proměnné
---> 10     lokalni += globalni
     11 
     12     # uvnitř funkce nelze měnit globální proměnné
     13     globalni += 1

UnboundLocalError: cannot access local variable 'globalni' where it is not associated with a value

Tip: Kliknutím na tlačítko pytutor v rozhraní JupyterLab se zobrazí grafická interpretace toho, co se v programu děje.

Pokud bychom uvnitř funkce použili přiřazení jako např. globalni = 1 v následujícím příkladu, není to chyba, ale je důležité si uvědomit, co se v programu děje. Příkaz přiřazení totiž vytváří novou proměnnou, ke které připojí daný název. V tomto případě tedy vzniká nová lokální proměnná s názvem globalni a hodnotou 1 a její název na lokální úrovni překryje globální proměnnou se stejným názvem, jde však o dva různé objekty:

In [32]:
# lokální proměnnou mohu pojmenovat stejně jako globální proměnnou
# uvnitř funkce lokální proměnná překryje globální proměnnou stejného jména

# globální proměnná
globalni = 10

def f():
    # zde dojde k vytvoření lokální proměnné, která překryje proměnnou na globální úrovni
    globalni = 1

    print("hodnota uvnitř funkce:", globalni)

# použití funkce
f()

# funkce f nezměnila globální proměnnou
print("hodnota mimo funkci:", globalni)
hodnota uvnitř funkce: 1
hodnota mimo funkci: 10

K podobné shodě názvu proměnných může docházet poměrně často, ale není třeba se tohoto chování bát. Vykonávání příkazů dané funkce probíhá ve svém vlastním lokálním světě, který s globálním světem komunikuje především pomocí vstupních parametrů a výstupní návratové hodnoty (viz dále). Spíš by bylo nepříjemné, kdyby funkce modifikovala okolní stav nějakým jiným, nepřehledným způsobem.

In [37]:
# Výhooda: uvnitř funkce si mohu pojmenovávat proměnné, jak chci
y = 8
from math import cos

def f(x, y):
    min = "minimum"
    cos = "cosi"
    print("uvnitř:", x + y, min, cos)
    return min

print(min(4, 6), cos(0))
y = f(6, y)
print(y)
print(min(4, 6), cos(0))
4 1.0
uvnitř: 14 minimum cosi
minimum
4 1.0
In [38]:
# uvnitř funkce mohu provést lokální import:
a = 10 # globální proměnná

def f(x): # parametr ... lokální proměnná
    from math import cos
    y = 1 + cos(x) # lokální proměnná
    print("lokalni", x, y, cos) # výpis lokálních proměnných
    
f(90) # použití funkce

# výpis globálních proměnných
print("globalni", a)
# y = cos(90) # chyba
# ukázka pytutor
lokalni 90 0.5519263838708299 <built-in function cos>
globalni 10
In [ ]:
# uvnitř funkce mohu použít globání import
a = 10 # globální proměnná
import math

def f(x): # parametr ... lokální proměnná
    y = 1 + x + math.cos(math.pi) # lokální proměnná
    print("lokalni", x, y) # výpis lokálních proměnných
    
f(90) # použití funkce

# výpis globálních proměnných
print("globalni", a)
# y = cos(90) # chyba
# ukázka pytutor

Příklady¶

  1. Definujte a zavolejte funkci je_dělitelné(n, d), která vrací True nebo False podle toho, jestli je zadané přirozené číslo n dělitelné číslem d.
In [44]:
def je_delitelne(n, d):
    if d == 0:
        return False
    if n % d == 0:
        return True
    return False
    
print(je_delitelne(15, 3))
print(je_delitelne(15, 5))
print(je_delitelne(15, 4))
print(je_delitelne(15, 15))
print(je_delitelne(15, 0))
print(je_delitelne(0, 3))
True
True
False
True
False
True
In [40]:
def je_delitelne(n, d):
    if d == 0:
        return False
    return n % d == 0
    
print(je_delitelne(15, 3))
print(je_delitelne(15, 5))
print(je_delitelne(15, 4))
print(je_delitelne(15, 15))
print(je_delitelne(15, 0))
print(je_delitelne(0, 3))
True
True
False
True
False
True
  1. Napište a zavolejte funkci počet_dělitelů(n), která spočítá a vrátí počet dělitelů přirozeného čísla n. Využijte funkci naprogramovanou v předchozím příkladu.
In [51]:
def pocet_delitelu(n):
    pocet = 0
    for d in range(1, n + 1):
        if je_delitelne(n, d):
            pocet += 1
    return pocet

print(pocet_delitelu(56))
print(pocet_delitelu(1))
print(pocet_delitelu(15))
8
1
4
  1. Napište a zavolejte funkci vypiš_dělitele(n), která vypíše všechny dělitele přirozeného čísla n.
In [42]:
def vypis_delitele(n):
    for d in range(1, n + 1):
        if je_delitelne(n, d):
            print(d, end = " ")
    print("")
    
vypis_delitele(56)
vypis_delitele(1)
vypis_delitele(15)

    
1 2 4 7 8 14 28 56 
1 
1 3 5 15 
In [44]:
for i in range(10):
    print(i, ": ", end="")
    vypis_delitele(i)
0 : 
1 : 1 
2 : 1 2 
3 : 1 3 
4 : 1 2 4 
5 : 1 5 
6 : 1 2 3 6 
7 : 1 7 
8 : 1 2 4 8 
9 : 1 3 9 
  1. Napište a zavolejte funkci bmi(hmotnost, výška), která ze zadaných parametrů spočítá index BMI a vrátí výsledek jako číselnou hodnotu.
In [45]:
# zadny print uvnitr funkce!
def bmi(m, h):
    vysledek = m / (h / 100) ** 2
    return vysledek

hmotnost = 60
vyska = 160

print(bmi(hmotnost, vyska))
print(bmi(80, 190))
23.437499999999996
22.1606648199446
  1. Naprogramujte funkci součet_číslic(n), která spočítá součet číslic v desítkovém zápisu přirozeného čísla n.
In [56]:
n = 7684
cislice = n % 10
n1 = n // 10
print(n, n1, cislice)
7684 768 4
In [58]:
n = 7684
while n != 0:
    cislice = n % 10
    n = n // 10
    print(cislice)
4
8
6
7
In [60]:
def soucet_cislic(n):
    soucet = 0
    while n != 0:
        cislice = n % 10
        n = n // 10
        soucet += cislice
    return soucet
    
print(soucet_cislic(7684))
print(soucet_cislic(10002))
25
3
  1. Naprogramujte funkci remove(n, digit), která z desítkového zápisu zadaného přirozeného čísla n odstraní všechny číslice, které se rovnají hodnotě digit. Např.:

    • remove(123, 2) → 13
    • remove(243132, 3) → 2412
In [62]:
n = 7684

nove_cislo = 0
nasobek = 1
while n != 0:
    cislice = n % 10
    n = n // 10
    print(cislice)
    nove_cislo += cislice * nasobek
    nasobek = nasobek * 10
nove_cislo
4
8
6
7
Out[62]:
7684
In [63]:
n = 7684
digit = 6

nove_cislo = 0
nasobek = 1
while n != 0:
    cislice = n % 10
    n = n // 10
    print(cislice)
    if cislice != digit:
        nove_cislo += cislice * nasobek
        nasobek = nasobek * 10
nove_cislo
4
8
6
7
Out[63]:
784
In [66]:
def remove(n, digit):
    
    nove_cislo = 0
    nasobek = 1
    while n != 0:
        cislice = n % 10
        n = n // 10
        if cislice != digit:
            nove_cislo += cislice * nasobek
            nasobek = nasobek * 10
    return nove_cislo

print(remove(764484, 4))
print(remove(764484, 5))
print(remove(764484, 7))
768
764484
64484

Pro procvičení můžete dále zkusit upravit libovolný příklad z předchozích cvičení a definovat v něm vhodnou funkci.