Rekurze (angl. recursion) je programátorská technika, kdy funkce volá sebe sama.
Jednoduchá rekurze skončí nekonečným voláním. Zkus zadat tento program:
def rekurzivni_funkce():
vysledek = ...
rekurzivni_funkce()
return vysledek
rekurzivni_funkce()
Jak to funguje?
rekurzivni_funkce
rekurzivni_funkce
:rekurzivni_funkce
:rekurzivni_funkce
:rekurzivni_funkce
:rekurzivni_funkce
:Tomu odpovídá chybová hláška:
Traceback (most recent call last):
File "/tmp/ukazka.py", line 4, in <module>
rekurzivni_funkce()
File "/tmp/ukazka.py", line 2, in rekurzivni_funkce
return rekurzivni_funkce()
File "/tmp/ukazka.py", line 2, in rekurzivni_funkce
return rekurzivni_funkce()
File "/tmp/ukazka.py", line 2, in rekurzivni_funkce
return rekurzivni_funkce()
[Previous line repeated 996 more times]
RecursionError: maximum recursion depth exceeded
Hláška je zkrácená – dva řádky by se správně měly opakovat 999×, ale novější verze Pythonu je vypíšou jen třikrát.
Jak rekurzi využít v praxi? Jeden způsob je si počítat, kolikrát se ještě „zanořit“.
Představ si potápěče, který prozkoumává mořské hlubiny následujícím způsobem:
Neboli v Pythonu:
def pruzkum(hloubka):
print(f'Rozhlížím se v hloubce {hloubka} m')
if hloubka >= 30:
print('Už toho bylo dost!')
else:
print(f'Zanořuju se (z {hloubka} m)')
pruzkum(hloubka + 10)
print(f'Vynořuju se (na {hloubka} m)')
pruzkum(0)
pruzkum
pruzkum
s hloubkou 0:Rozhlížím se v hloubce 0 m
0 ≥ 30
(což neplatí)Zanořuju se (z 0 m)
pruzkum
s hloubkou 10 m:Rozhlížím se v hloubce 10 m
10 ≥ 30
(což neplatí)Zanořuju se (z 10 m)
pruzkum
s hloubkou 20 m:Rozhlížím se v hloubce 20 m
20 ≥ 30
(což neplatí)Zanořuju se (z 20 m)
pruzkum
s hloubkou 30 m:Rozhlížím se v hloubce 30 m
30 ≥ 30
(což platí! konečně!)Už toho bylo dost!
Vynořuju se (na 20 m)
Vynořuju se (na 10 m)
Vynořuju se (na 0 m)
Na předchozím příkladu je vidět zajímavé chování lokálních proměnných. Když je potápěč „na dně“, jakou hodnotu má proměnná hloubka?
Tahle otázka je chyták. Která proměnná hloubka
?
Když je program „na dně“, existují čtyři různé lokální proměnné hloubka
:
každé zanoření, každé zavolání funkce pruzkum
, má vlastní proměnnou.
Podobně jako když máš globální a lokální proměnnou stejného jména, každá funkce „vidí“ jen tu svoji proměnnou. Ale když se potápěč vynoří a volání funkce se ukončí, tato proměnná přestane existovat. A „volající“ funkce vidí svoji proměnnou, ve které je stále původní hodnota.
Nemáš-li ráda matematiku, tuhle sekci přeskoč!
Rekurzivní algoritmy mají původ v matematice. Faktoriál x, neboli součin všech čísel od 1 do x, zapsaný jako x!, matematici definují takto:
Neboli v Pythonu:
def factorial(x):
if x == 0:
return 1
elif x > 0:
return x * factorial(x - 1)
print(factorial(5))
print(1 * 2 * 3 * 4 * 5)