Už umíš definovat vlastní funkce. Zbývá ale ještě dovysvětlit, jak v nich fungují proměnné.
Funkce může používat proměnné „zvnějšku“.
Následující program přiřadí do proměnné pi a všechny další funkce
mají k pi přístup:
pi = 3.1415926
def obsah_kruhu(polomer):
return pi * polomer ** 2
print(obsah_kruhu(100))
Jinak je tomu ale v případě, kdy proměnnou nastavíš uvnitř funkce.
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ěmto 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.
Proměnné, které nejsou lokální, jsou globální – ty existují v celém programu.
Pro příklad:
def nastav_x(hodnota):
x = hodnota # Přiřazení do lokální proměnné!
nastav_x(40)
print('x =', x)
Program skončí s chybou!
Funkce nastav_x si hraje na vlastním písečku; proměnná x je jen
pro ni.
Když funkce nastav_x skončí, proměnná x přestane existovat.
Podobně skončí s chybou i složitější program:
def zamen(slovo, pozice, novy_znak):
"V daném slově zamění znak na dané pozici za daný nový znak"
zacatek = slovo[:pozice]
konec = slovo[pozice + 1:]
nove_slovo = zacatek + novy_znak + konec
return nove_slovo
print(zamen('kočka', 1, 'a'))
print(zamen('kačka', 2, 'p'))
print(zacatek) # NameError
Funkce zamen jsi napsala proto, abys nemusela pořád opakovat detaily
záměny písmenka.
Jakmile je jednu nadefinovaná, stačí ji zavolat. Důležité jsou jen jméno
funkce, argumenty a návratová hodnota; na detaily kódu uvnitř můžeš zapomenout.
A to i díky lokálním proměnným, které detaily ve vnitřku funkce trochu líp
izolují od zbytku programu.
Ještě lépe je to vidět u funkcí, které jsi nenapsala sama.
Jak divné by bylo, kdyby po každém zavolání print byla najednou nastavená
proměnná i, kterou print náhodou používá při procházení svých argumentů!
To, co dělá lokální proměnnou, je přiřazení.
Porovnej nastav_x s příkladem na obsah_kruhu výše: rozdíl mezi pi a x
je v tom, že do x se v rámci funkce funkce přiřazuje.
Co je to přiřazení? Všechno, co nastavuje nějakou proměnnou. Například:
=, např. a = 3.def nastav_x(hodnota) přiřadí do hodnota,for x in ...: přiřazuje do proměnné x.def x(...):, import x a from ... import x taky
přiřazují do x – ale ve funkcích se moc nepoužívají.A další
K těmto materiálům se možná budeš vracet, tak pro úplnost přidám další způsoby, které postupně poznáš. Není jich mnoho:
with ... as x, del x, except ... as x přiřazují do x.+=, *=, :=.Jak to funguje, když ve funkci přiřadíš do proměnné, která existuje i globálně? Pak tu máme problém.
Vytvoří se úplně nová lokální proměnná, která má stejné jméno jako ta globální. Jméno označuje lokální proměnnou, a ta globální pak „není vidět“.
Tento příklad tedy nebude fungovat tak, jak se zdá:
x = 0
def nastav_x(hodnota):
x = hodnota # Přiřazení do lokální proměnné!
print('Ve funkci nastav_x: x =', x)
nastav_x(40)
print('Venku: x =', x)
V tomto programu existují dvě proměnné jménem x.
Jedna je globální. Jedna je lokální pro funkci nastav_x.
Jmenují se stejně, ale jsou to dvě různé proměnné.
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 na chytáky!
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)
Zkus odpovědět na tyto otázky:
pi lokální, nebo globální?obsah lokální, nebo globální?a lokální, nebo globální?b lokální, nebo globální?obsah_elipsy lokální, nebo globální?Pravidla pro lokální proměnné jsou pro začátečníky jednou z nejzvláštnějších věcí v Pythonu. Jsou ale užitečná – umožňují některé užitečné techniky, např. rekurzi.
Jestli ti to celé připadá 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í.)