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

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

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 [5]:
# již známe 2 druhy funkcí: funkce, co mají nějaké parametry a vrací hodnotu 
# a funkci print pro vypisování
x = abs(-7)
print(x)
7

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 [6]:
# 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'.")
In [7]:
# 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
x = 7

# ukázka: debugger

Funkce print_demo1 má jeden parametr:

In [8]:
# Tato funkce má jeden parametr a vrací hodnotu None
def print_demo1(param):
    print("Hodnota parametru je", param)

Funkce print_demo2 má dva parametry:

In [9]:
# Tato funkce má dva parametry a vrací hodnotu None
def print_demo2(param1, param2):
    print("Hodnota prvního parametru je", param1)
    print("Hodnota druhého parametru je", param2)

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.

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

In [10]:
# výpis hodnoty, na kterou odkazuje proměnná 'x': číslo
print(x)
7
In [11]:
# výpis hodnoty, na kterou odkazuje proměnná 'print_demo':
# objekt, který reprezentuje funkci
print(print_demo)
<function print_demo at 0x7fe82ad63e20>

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 [12]:
# Volání funkce:
print_demo()
Byla spuštěna funkce 'print_demo'.
In [15]:
# 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
In [13]:
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 [14]:
# funkci musíme volat se správným počtem argumentů
print_demo1()
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Cell In[14], line 1
----> 1 print_demo1()

TypeError: print_demo1() missing 1 required positional argument: 'param'
In [18]:
# funkci musíme volat se správným počtem argumentů
print_demo1(1, 2, 3)
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Cell In[18], line 1
----> 1 print_demo1(1, 2, 3)

TypeError: print_demo1() takes 1 positional argument but 3 were given

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 [19]:
def say_hello(name):
    print("Hello", name)

say_hello("Petr")
say_hello("Anna")
Hello Petr
Hello Anna
Hello 0
Hello 1
Hello 2
Hello 3
Hello 4
In [20]:
for i in range(5):
    say_hello(i)
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 [21]:
# 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 [38]:
# před příkazem return může být složitější výpočet:
def polynom1(x):
    vysl = x ** 2 - 3 * x
    vysl += 1
    return vysl

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

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

# ukázka: debugger + pytutor
-0.25
-0.25
In [23]:
# volání funkcí může být součástí složitějších výrazů
x = polynom(5) + 4 * polynom1(0.3)
print(x)
11.76
In [39]:
# příkaz return okamžitě ukončí funkci (jako break u cyklu)
def polynom2(x):
    vysl = 1
    return vysl
    print("ahoj")
    vysl = x ** 2 - 3 * x
    return vysl

vysledek = polynom2(2.5)
print(vysledek)
1

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 [25]:
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(-1)
print(vysledek)
Definiční obor této funkce nezahrnuje záporná čísla.
None
In [26]:
# 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
    elif x == 0:
        return 0
    return -1
print(signum(-6))
-1
In [1]:
# pokud funkce neobsahuje příkaz return, je její návratovou hodnotou None:
def say_hello(name):
    print("Hello", name)

x = say_hello("anna")
print(x)
Hello anna
None
In [3]:
if say_hello("Petr"):
    print("ano")
else:
    print("Hodnota None se vyhodnotí jako False")
Hello Petr
Hodnota None se vyhodnot9 jako False
In [40]:
# tato funkce vypisuje pozdrav a vrací hodnotu 2
def say_hello(name):
    print("Hello", name)
    return 2

x = say_hello("anna")
print(x)
Hello anna
None
In [45]:
# funkce vrací pro hodnotu argumentu 'petr' hodnotu 1 a jindy 'None'
def say_hello(name):
    print("hello", name)
    if name == "petr":
        return 1
In [46]:
x = say_hello("petra")
print(x)
hello petra
None
In [47]:
x = say_hello("petr")
print(x)
hello petr
1

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 [29]:
def je_sude(n):
    if n % 2 == 0:
        return True
    else:
        return False
        
print(je_sude(2), je_sude(3))
n = 10
if je_sude(n):
    print("ano")
True False
ano
In [30]:
def je_sude(n):
    return  n % 2 == 0
        
print(je_sude(2), je_sude(3))
n = 10
if je_sude(n):
    print("ano")
True False
ano
In [31]:
def je_sude(n):
    return not (n % 2) 
        
print(je_sude(2), je_sude(3))
n = 10
if je_sude(n):
    print("ano")
True False
ano
  1. Analogicky napište funkci je_liché(n). Využijte při tom předchozí funkci. Funkci zavolejte.
In [32]:
def je_liche(n):
    if je_sude(n):
        return False
    else:
        return True
print(je_liche(2), je_liche(3))
False True
In [33]:
def je_liche(n):
    return not je_sude(n)
print(je_liche(2), je_liche(3))
False True

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 [48]:
# Proměnné dělíme na globální (definované na úrovni programu) 
# a lokální (definované na úrovni funkce)
a = 10 # globální proměnná

def f():
    x = 1 # lokální proměnná
    print("lokalni", x) # výpis lokálních proměnných
    
f() # použití funkce

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

def f():
    x = 1 # lokální proměnná
    print("lokalni", x) # výpis lokálních proměnných
    
f() # použití funkce

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

# chyba:
print("lokalni", x)
lokalni 1
globalni 10
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[1], line 14
     11 print("globalni", a)
     13 # chyba:
---> 14 print("lokalni", x)

NameError: name 'x' is not defined
In [4]:
# Proměnné dělíme na globální (definované na úrovni programu) 
# a lokální (definované na úrovni funkce)
a = 10 # globální proměnná

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

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

# ukázka pytutor
lokalni 2 3
globalni 10
In [6]:
# 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
a = 10 # globální proměnná
x = "ahoj"
y = "lidi"

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

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

# ukázka pytutor
lokalni 2 3
globalni 10 ahoj lidi
In [14]:
# Výhooda: uvnitř funkce si mohu pojmenovávat proměnné, jak chci
a = 10 # globální proměnná
from math import cos
x = "ahoj"
y = "lidi"

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

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

# funguje dle očekávání
print(min(10, 9))
# ukázka pytutor
lokalni 2 3 7 9
globalni 10 ahoj lidi <built-in function cos>
9
In [10]:
# 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 [13]:
# 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
lokalni 90 90.0
globalni 10
In [15]:
# uvnitř funkce mohu použít globální proměnné (ale nedoporučuji to)
a = 10 # globální proměnná


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

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

# ukázka pytutor
lokalni 2 13
globalni 10
In [16]:
# uvnitř funkce nemohu globální proměnné měnit
# tj. jakmile uvnitř funkce použiju globální proměnnou, již nesmím definovat
# lokální proměnnou stejného jména:

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

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

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

# ukázka pytutor
---------------------------------------------------------------------------
UnboundLocalError                         Traceback (most recent call last)
Cell In[16], line 10
      7     print("lokalni", x, y) # výpis lokálních proměnných
      8     a = 10
---> 10 f(2) # použití funkce
     12 # výpis globálních proměnných
     13 print("globalni", a)

Cell In[16], line 6, in f(x)
      5 def f(x): # parametr ... lokální proměnná
----> 6     y = 1 + x + a # lokální proměnná
      7     print("lokalni", x, y) # výpis lokálních proměnných
      8     a = 10

UnboundLocalError: cannot access local variable 'a' where it is not associated with a value
In [4]:
# globální proměnná
a = 10
import math

def f(y):
    from math import sin
    # lokální proměnná
    z = sin(y)
    x = 1 + y + math.pi + a + z

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

print(math.pi)

# použití funkce
f(8)

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

sin(math.pi)
3.141592653589793
lokalni 23.130950900213175 8
globalni 10
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[4], line 22
     19 # výpis globálních proměnných
     20 print("globalni", a)
---> 22 sin(math.pi)

NameError: name 'sin' is not defined
In [ ]:
# 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)

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 [ ]:
# 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)

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.

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 [17]:
# zadny print uvnitr funkce!
def je_delitelne(n, d):
    if n % d == 0:
        return True
    return False
In [ ]:
def je_delitelne(n, d):
    return n % d == 0
In [ ]:
print(je_delitelne(10, 2))
print(je_delitelne(10, 1))
print(je_delitelne(10, 3))
print(je_delitelne(13, 2))
  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 [21]:
# zadny print uvnitr funkce!
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(30))
for n in range(21):
    print(n, ":", pocet_delitelu(n))
8
0 : 0
1 : 1
2 : 2
3 : 2
4 : 3
5 : 2
6 : 4
7 : 2
8 : 4
9 : 3
10 : 4
11 : 2
12 : 6
13 : 2
14 : 4
15 : 4
16 : 5
17 : 2
18 : 6
19 : 2
20 : 6
  1. Napište a zavolejte funkci vypiš_dělitele(n), která vypíše všechny dělitele přirozeného čísla n.
In [22]:
# tady naopak print bude
def vypis_delitele(n):
    for d in range(1, n + 1):
        if je_delitelne(n, d):
            print(d, end = " ")
vypis_delitele(30)
print()
vypis_delitele(1)
print()
vypis_delitele(-1)
1 2 3 5 6 10 15 30 
1 
In [23]:
for i in range(10):
    print(i, ": ", end="")
    vypis_delitele(i)
    print("")
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 [26]:
# zadny print uvnitr funkce!
def bmi(hmotnost, výška):
    return hmotnost / (výška**2)

bmi(60, 1.7)
Out[26]:
20.761245674740486
  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 [27]:
n = 12345
cislice = n % 10
n = n // 10
print(cislice, n)
5 1234
In [ ]:
# zadny print uvnitr funkce!
n = 145
def soucet_cislic(n):
    soucet = 0
    while n > 0:
        cislice = n % 10
        n = n // 10
        soucet += cislice
    return soucet
print(soucet_cislic(12345), n)
  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 [ ]:
 

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.