Cvičení č. 7 rozšířené o poznámky ze cvičení a řešení některých příkladů (ZS 2024/25)¶
V minulém díle jste viděli...¶
Podmíněný příkaz if
s volitelnými bloky elif
a else
:
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:
x = -1
y = 2
z = x if x + y > 0 else y
Příkaz while
:
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:
for n in range(100, 20, -2):
print(n, end = " ")
100 98 96 94 92 90 88 86 84 82 80 78 76 74 72 70 68 66 64 62 60 58 56 54 52 50 48 46 44 42 40 38 36 34 32 30 28 26 24 22
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).
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:
# 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'.")
# 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 = 5+7
# ukázka: debugger
Funkce print_demo1
má jeden parametr:
# Tato funkce má jeden parametr a vrací hodnotu None
def print_demo1(param):
print("Hodnota parametru je", param)
Funkce print_demo2
má dva parametry:
# 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.
# Volání funkce:
print_demo()
Byla spuštěna funkce 'print_demo'.
# Volání funkce s jedním paraetrem, "ahoj" je argument pro parametr 'param'
print_demo1("ahoj")
print_demo1(12)
Hodnota parametru je ahoj Hodnota parametru je 12
# ukázka: debugger, pytutor
x = print_demo1("ahoj")
print(x)
Hodnota parametru je ahoj None
Výpis samotného objektu reprezentujícího funkci vypadá takto:
# výpis objektu, který reprezentuje funkci:
print(print_demo)
<function print_demo at 0x7e7b583118a0>
# funkce vrací None:
if print_demo:
print("ano")
ano
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ě:
# ukázka: funkci musím volat se správným počtem argumentů
print_demo2(5+5)
--------------------------------------------------------------------------- TypeError Traceback (most recent call last) Cell In[12], line 2 1 # ukázka: volání funkce, správný počet argumentů ----> 2 print_demo2(5+5) TypeError: print_demo2() missing 1 required positional argument: 'param2'
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
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.
def say_hello(name):
print("Hello", name)
say_hello("Anna")
say_hello("Petr")
say_hello(123)
Hello Anna Hello Petr Hello 123
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:
# K vrácení výsledné (návratové) hodnoty funkce slouží příkaz return:
def polynom(x):
return x ** 2 - 3 * x + 1
def polynom1(x):
vysledek = x ** 2 - 3 * x + 1
return vysledek
# výslednou (návratovou) hodnotu funkce mohu např. vložit do proměnné:
vysledek = polynom(0.5)
print(vysledek)
# nebo rovnou vypsat:
print(polynom1(2.5))
# volání funkcí může být součástí složitějších výrazů
vysledek = polynom(2.5-4) + 3 - polynom(2.5) ** 2
print(vysledek)
# volání funkce v cyklu:
for i in range(-10,10):
print(polynom(i), end = " ")
-0.25 -0.25 10.6875 131 109 89 71 55 41 29 19 11 5 1 -1 -1 1 5 11 19 29 41 55
# 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
# tato funkce vrací hodnotu 6:
def say_hello(name):
print("Hello", name)
return 6
x = say_hello("anna")
print(x)
Hello anna 6
# příkaz return okamžitě ukončí funkci (jako break u cyklu)
# za příkazem return může a nemusí následovat návratová hodnota
# pokud žádnou návratovou hodnotu nespecifikujeme, vrátí se None
def say_hello(name):
return
print("Hello", name)
x = say_hello("anna")
print(x)
None
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
:
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(-3)
print(vysledek)
Definiční obor této funkce nezahrnuje záporná čísla. None
# 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
else:
return -1
for i in range(-10, 10):
print(signum(i), end = " ")
-1 -1 -1 -1 -1 -1 -1 -1 -1 -1 0 1 1 1 1 1 1 1 1 1
Příklad¶
- Napište funkci
je_sudé(n)
, která vracíTrue
neboFalse
podle toho, jestli je zadané přirozené číslon
sudé nebo není. Funkci zavolejte.
def je_sude(n):
if n % 2 == 0:
return True
else:
return False
print(je_sude(10), je_sude(11))
True False
def je_sude(n):
return n % 2 == 0
print(je_sude(10), je_sude(11))
True False
def je_sude(n):
return not n % 2
print(je_sude(10), je_sude(11))
True False
- Analogicky napište funkci
je_liché(n)
. Využijte při tom předchozí funkci. Funkci zavolejte.
def je_liche(n):
if not je_sude(n):
return True
else:
return False
print(je_liche(10), je_liche(11))
False True
def je_liche(n):
return je_sude(n) == False
print(je_liche(10), je_liche(11))
False True
def je_liche(n):
return not je_sude(n)
print(je_liche(10), je_liche(11))
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.
# Proměnné dělíme na globální (definované na úrovni programu)
# a lokální (definované na úrovni funkce)
# globální proměnná
a = 10
def f(x): # parametr funkce ... lokální proměnná
y = x + 1 # lokální proměnná
print("lokalni", x, y)
f(2 + 3)
print("globalni", a)
lokalni 5 6 globalni 10
# lokální proměnná žije jen uvvnitř funkce, když funkce skončí, zanikne:
a = 10
def f(x):
y = x + 1
print("lokalni", x, y)
f(2 + 3)
print("globalni", a)
print("lokalni", y)
lokalni 5 6 globalni 10
--------------------------------------------------------------------------- NameError Traceback (most recent call last) Cell In[37], line 10 8 f(2+3) 9 print("globalni", a) ---> 10 print("lokalni", y) NameError: name 'y' is not defined
# 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
def f(x):
y = x + 1
a = 16
print("lokalni", x, y)
print("lokalni", a)
f(2 + 3)
print("globalni", a)
lokalni 5 6 lokalni 16 globalni 10
# globální proměnnou mohu použít uvnitř funkce:
a = 10
def f(x):
y = x + 1 + a
print("lokalni", x, y)
print("globalni", a)
f(5+3)
print("globalni", a)
lokalni 8 19 globalni 10 globalni 10
# uvnitř funkce mohu použít globální import:
a = 10
import math
def f(x, a):
y = x + 1 + a + math.cos(45)
print("lokalni", x, y)
print("globalni", a)
f(5+3, a)
print("globalni", a)
lokalni 8 19.52532198881773 globalni 10 globalni 10
# uvnitř funkce mohu provést lokální import:
a = 10
pi = "ahoj"
def f(x, a):
from math import pi
y = x + 1 + a + pi
print("lokalni", x, y, pi)
print("globalni", a)
f(5+3, a)
print("globalni", a, pi)
lokalni 8 22.141592653589793 3.141592653589793 globalni 10 globalni 10 ahoj
# globální proměnnou nemohu uvnitř funkce měnit:
a = 10
def f(x):
y = x + 1 + a
a += 1
print("lokalni", x, y)
print("globalni", a)
f(5+3)
print("globalni", a)
--------------------------------------------------------------------------- UnboundLocalError Traceback (most recent call last) Cell In[42], line 10 7 print("lokalni", x, y) 8 print("globalni", a) ---> 10 f(5+3) 11 print("globalni", a) Cell In[42], line 5, in f(x) 4 def f(x): ----> 5 y = x + 1 + a 6 a += 1 7 print("lokalni", x, y) UnboundLocalError: cannot access local variable 'a' where it is not associated with a value
# jakmile uvnitř funkce použiju globální proměnnou, již nesmím definovat
# lokální proměnnou stejného jména:
a = 10
def f(x):
y = x + 1 + a
a += 1
print("lokalni", x, y)
print("globalni", a)
f(5+3)
print("globalni", a)
--------------------------------------------------------------------------- UnboundLocalError Traceback (most recent call last) Cell In[42], line 10 7 print("lokalni", x, y) 8 print("globalni", a) ---> 10 f(5+3) 11 print("globalni", a) Cell In[42], line 5, in f(x) 4 def f(x): ----> 5 y = x + 1 + a 6 a += 1 7 print("lokalni", x, y) UnboundLocalError: cannot access local variable 'a' where it is not associated with a value
# ukázka funkce s jedním parametrem a lokální proměnnou, pytutor
a = 10
x = "ahoj"
y = "neco"
from math import cos
def f(x):
y = x + 1
cos = 67
print("lokalni", x, y, cos)
f(5+3)
print("globalni", a, x, y, cos(1))
lokalni 8 9 67 globalni 10 ahoj neco 0.5403023058681398
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:
# 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
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:
# 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.
Příklady¶
- Napište funkci
je_dělitelné(n, d)
, která vracíTrue
neboFalse
podle toho, jestli je zadané přirozené číslon
dělitelné číslemd
.
def je_dělitelné(n, d):
return n % d == 0
n = 10
for i in range(1, n + 1):
print(n, i, ":", je_dělitelné(n, i))
10 1 : True 10 2 : True 10 3 : False 10 4 : False 10 5 : True 10 6 : False 10 7 : False 10 8 : False 10 9 : False 10 10 : True
- Napište funkci
počet_dělitelů(n)
, která spočítá a vrátí počet dělitelů přirozeného číslan
. Využijte funkci naprogramovanou v předchozím příkladu.
def počet_dělitelů(n):
if n <= 0:
return
počet = 0
for i in range(1,n+1):
if je_dělitelné(n,i):
počet += 1
return počet
for i in range(10):
print(i, počet_dělitelů(i))
0 None 1 1 2 2 3 2 4 3 5 2 6 4 7 2 8 4 9 3
- Napište funkci
vypiš_dělitele(n)
, která vypíše všechny dělitele přirozeného číslan
.
def vypiš_dělitele(n):
for i in range(1,n+1):
if je_dělitelné(n,i):
print(i, end = " ")
for i in range(10):
print(i, ": ", end="")
vypiš_dělitele(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
- Napište funkci
bmi(hmotnost, výška)
, která ze zadaných parametrů spočítá index BMI a vrátí výsledek jako číselnou hodnotu.
def bmi(hmotnost, výška):
return hmotnost / (výška**2)
hmotnost = float(input("Zadej svou hmotnost v kg:"))
výška = float(input("Zadej svou výšku v m:"))
bmi_výsledek = bmi(hmotnost, výška)
print("Vaše bmi je", bmi_výsledek)
print(f"Vaše bmi je {bmi_výsledek:.1f}.")
Vaše bmi je 22.03856749311295 Vaše bmi je 22.0.
- Naprogramujte funkci
součet_číslic(n)
, která spočítá součet číslic v desítkovém zápisu přirozeného číslan
.
def součet_číslic(n):
součet = 0
while n > 0:
součet += n % 10
n //= 10
return součet
print(součet_číslic(456))
15
Naprogramujte funkci
remove(n, digit)
, která z desítkového zápisu zadaného přirozeného číslan
odstraní všechny číslice, které se rovnají hodnotědigit
. Např.:remove(123, 2)
→13
remove(243132, 3)
→2412
def remove(n, digit):
výsledek = 0 # Výsledek
násobek = 1
while n > 0:
číslice = n % 10 # Získej poslední číslici
n //= 10 # Odstraň poslední číslici
# Pokud číslice není digit, přidej ji k výsledku
if číslice != digit:
výsledek += číslice * násobek
násobek *= 10 # Posuň násobek na další pozici
return výsledek
print(remove(321353,3))
print(remove(444444,4))
215 0
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.