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.
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
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í.)
{ "data": { "sessionMaterial": { "id": "session-material:2019/brno-jaro-2019-pondeli:file:3", "title": "Lokální proměnné", "html": "\n \n \n\n <h1>Lokální proměnné</h1>\n<p>Už umíš definovat vlastní funkce.\nZbývá ale ještě dovysvětlit, jak v nich fungují proměnné.</p>\n<p>Funkce může používat proměnné „zvnějšku“.\nNásledující program přiřadí do proměnné <code>pi</code> a všechny další funkce\nmají k <code>pi</code> přístup:</p>\n<div class=\"highlight\"><pre><span></span><span class=\"n\">pi</span> <span class=\"o\">=</span> <span class=\"mf\">3.1415926</span>\n\n<span class=\"k\">def</span> <span class=\"nf\">obsah_kruhu</span><span class=\"p\">(</span><span class=\"n\">polomer</span><span class=\"p\">):</span>\n <span class=\"k\">return</span> <span class=\"n\">pi</span> <span class=\"o\">*</span> <span class=\"n\">polomer</span> <span class=\"o\">**</span> <span class=\"mi\">2</span>\n\n<span class=\"k\">print</span><span class=\"p\">(</span><span class=\"n\">obsah_kruhu</span><span class=\"p\">(</span><span class=\"mi\">100</span><span class=\"p\">))</span>\n</pre></div><p>Jinak je tomu ale v případě, kdy proměnnou nastavíš <em>uvnitř</em> funkce.</p>\n<p>Všechny argumenty a všechny proměnné, do kterých funkce přiřazuje,\njsou <em>úplně nové</em> proměnné, které nemají nic\nspolečného s tím, co je „venku“ kolem funkce.</p>\n<p>Těmto proměnným se říká <em>lokální proměnné</em> (angl. <em>local variables</em>),\nprotože existují jen místně, v rámci volání jedné jediné funkce.</p>\n<p>Proměnné, které nejsou lokální, jsou <em>globální</em> – ty existují v celém programu.</p>\n<p>Pro příklad:</p>\n<div class=\"highlight\"><pre><span></span><span class=\"k\">def</span> <span class=\"nf\">nastav_x</span><span class=\"p\">(</span><span class=\"n\">hodnota</span><span class=\"p\">):</span>\n <span class=\"n\">x</span> <span class=\"o\">=</span> <span class=\"n\">hodnota</span> <span class=\"c1\"># Přiřazení do lokální proměnné!</span>\n\n<span class=\"n\">nastav_x</span><span class=\"p\">(</span><span class=\"mi\">40</span><span class=\"p\">)</span>\n<span class=\"k\">print</span><span class=\"p\">(</span><span class=\"s1\">'x ='</span><span class=\"p\">,</span> <span class=\"n\">x</span><span class=\"p\">)</span>\n</pre></div><p>Program skončí s chybou!\nFunkce <code>nastav_x</code> si hraje na vlastním písečku; proměnná <code>x</code> je jen\npro ni.\nKdyž funkce <code>nastav_x</code> skončí, proměnná <code>x</code> přestane existovat.</p>\n<h2>Přiřazení</h2>\n<p>To, co dělá lokální proměnnou, je <em>přiřazení</em>.\nPorovnej <code>nastav_x</code> s příkladem na <code>obsah_kruhu</code> výše: rozdíl mezi <code>pi</code> a <code>x</code>\nje v tom, že do <code>x</code> funkce přiřazuje.</p>\n<p>Co je to přiřazení? Všechno, co <em>nastavuje</em> nějakou proměnnou. Například:</p>\n<ul>\n<li>Klasika je přiřazovat pomocí <code>=</code>, např. <code>a = 3</code>.</li>\n<li>Argumenty funkce: funkce <code>def nastav_x(hodnota)</code> přiřadí do <code>hodnota</code>,</li>\n<li>Cyklus <code>for x in ...:</code> přiřazuje do proměnné <code>x</code>.</li>\n<li>Pro úplnost, příkazy <code>def x(...):</code>, <code>import x</code> a <code>from ... import x</code> taky\npřiřazují do <code>x</code> – ale ve funkcích se moc nepoužívají.</li>\n</ul>\n<div class=\"admonition note\"><p class=\"admonition-title\">A další</p>\n<p>K těmto materiálům se možná budeš vracet, tak pro úplnost přidám další\nzpůsoby, které postupně poznáš. Není jich mnoho:</p>\n<ul>\n<li>Příkazy <code>with ... as x</code>, <code>del x</code>, <code>except ... as x</code> přiřazují do <code>x</code>.</li>\n<li>Přiřazují i speciální přiřazovací operátory jako <code>+=</code>, <code>*=</code>, <code>:=</code>.</li>\n</ul>\n</div><h2>Zakrývání jména</h2>\n<p>Jak to funguje, když ve funkci přiřadíš do proměnné, která existuje i globálně?\nPak tu máme problém.</p>\n<p>Vytvoří se <em>úplně nová</em> lokální proměnná, která má stejné jméno jako\nta globální.\nJméno označuje lokální proměnnou, a ta globální pak „není vidět“.</p>\n<p>Tento příklad tedy nebude fungovat tak, jak se zdá:</p>\n<div class=\"highlight\"><pre><span></span><span class=\"n\">x</span> <span class=\"o\">=</span> <span class=\"mi\">0</span>\n\n<span class=\"k\">def</span> <span class=\"nf\">nastav_x</span><span class=\"p\">(</span><span class=\"n\">hodnota</span><span class=\"p\">):</span>\n <span class=\"n\">x</span> <span class=\"o\">=</span> <span class=\"n\">hodnota</span> <span class=\"c1\"># Přiřazení do lokální proměnné!</span>\n <span class=\"k\">print</span><span class=\"p\">(</span><span class=\"s1\">'Ve funkci nastav_x: x ='</span><span class=\"p\">,</span> <span class=\"n\">x</span><span class=\"p\">)</span>\n\n<span class=\"n\">nastav_x</span><span class=\"p\">(</span><span class=\"mi\">40</span><span class=\"p\">)</span>\n<span class=\"k\">print</span><span class=\"p\">(</span><span class=\"s1\">'Venku: x ='</span><span class=\"p\">,</span> <span class=\"n\">x</span><span class=\"p\">)</span>\n</pre></div><p>V tomto programu existují <em>dvě</em> proměnné jménem <code>x</code>.\nJedna je globální. Jedna je lokální pro funkci <code>nastav_x</code>.\nJmenují se stejně, ale jsou to dvě různé proměnné.</p>\n<h2>Lokální nebo globální?</h2>\n<p>Pojďme si to ukázat.\nNež spustíš tenhle program, zkus předpovědět, co bude dělat.\nPak ho pusť, a pokud dělal něco jiného, zkus vysvětlit proč.\nPozor na chytáky!</p>\n<div class=\"highlight\"><pre><span></span><span class=\"kn\">from</span> <span class=\"nn\">math</span> <span class=\"kn\">import</span> <span class=\"n\">pi</span>\n<span class=\"n\">obsah</span> <span class=\"o\">=</span> <span class=\"mi\">0</span>\n<span class=\"n\">a</span> <span class=\"o\">=</span> <span class=\"mi\">30</span>\n\n<span class=\"k\">def</span> <span class=\"nf\">obsah_elipsy</span><span class=\"p\">(</span><span class=\"n\">a</span><span class=\"p\">,</span> <span class=\"n\">b</span><span class=\"p\">):</span>\n <span class=\"n\">obsah</span> <span class=\"o\">=</span> <span class=\"n\">pi</span> <span class=\"o\">*</span> <span class=\"n\">a</span> <span class=\"o\">*</span> <span class=\"n\">b</span> <span class=\"c1\"># Přiřazení do `obsah`</span>\n <span class=\"n\">a</span> <span class=\"o\">=</span> <span class=\"n\">a</span> <span class=\"o\">+</span> <span class=\"mi\">3</span> <span class=\"c1\"># Přiřazení do `a`</span>\n <span class=\"k\">return</span> <span class=\"n\">obsah</span>\n\n<span class=\"k\">print</span><span class=\"p\">(</span><span class=\"n\">obsah_elipsy</span><span class=\"p\">(</span><span class=\"n\">a</span><span class=\"p\">,</span> <span class=\"mi\">20</span><span class=\"p\">))</span>\n<span class=\"k\">print</span><span class=\"p\">(</span><span class=\"n\">obsah</span><span class=\"p\">)</span>\n<span class=\"k\">print</span><span class=\"p\">(</span><span class=\"n\">a</span><span class=\"p\">)</span>\n</pre></div><p>Zkus odpovědět na tyto otázky:</p>\n<ul>\n<li>Je proměnná <code>pi</code> lokální, nebo globální?</li>\n<li>Je proměnná <code>obsah</code> lokální, nebo globální?</li>\n<li>Je proměnná <code>a</code> lokální, nebo globální?</li>\n<li>Je proměnná <code>b</code> lokální, nebo globální?</li>\n<li>Je proměnná <code>obsah_elipsy</code> lokální, nebo globální?</li>\n</ul>\n<div class=\"solution\" id=\"solution-0\">\n <h3>Řešení</h3>\n <div class=\"solution-cover\">\n <a href=\"/2019/brno-jaro-2019-pondeli/beginners/local-variables/index/solutions/0/\"><span class=\"link-text\">Ukázat řešení</span></a>\n </div>\n <div class=\"solution-body\" aria-hidden=\"true\">\n <ul>\n<li><code>pi</code> je globální – nepřiřazuje se do ní ve funkci;\nje „vidět“ v celém programu.</li>\n<li>Proměnné <code>obsah</code> jsou v programu dvě – jedna globální,\na jedna je lokální pro funkci <code>obsah_elipsy</code>,\nprotože do ní tahle funkce přiřazuje.</li>\n<li>Proměnné <code>a</code> jsou taky dvě, podobně jako <code>obsah</code>.\nTady byl chyták: příkaz <code>a = a + 3</code> nemá žádný smysl;\ndo <code>a</code> se sice uloží větší číslo, ale vzápětí funkce <code>obsah_elipsy</code> skončí\na její lokální proměnná <code>a</code> přestane existovat.</li>\n<li>Proměnná <code>b</code> je jenom lokální – jako argument funkce <code>obsah_elipsy</code>.</li>\n<li>Proměnná <code>obsah_elipsy</code> je globální (a je v ní funkce).</li>\n</ul>\n<div class=\"admonition note\"><p class=\"admonition-title\">A pro úplnost</p>\n<ul>\n<li>Klíčová slova <code>from</code>, <code>import</code>, <code>def</code>, <code>return</code> nejsou proměnné.</li>\n<li>Jméno modulu <code>math</code> není proměnná.</li>\n<li>Proměnná <code>print</code> se dá považovat za globální.\n(Ve skutečnosti existuje zvláštní kategorie <em>zabudovaných</em> (angl. <em>builtin</em>)\nproměnných.)</li>\n</ul>\n</div>\n </div>\n</div><h2>Rada na závěr</h2>\n<p>Pravidla pro lokální proměnné jsou pro začátečníky jednou z nejzvláštnějších \nvěcí v Pythonu.\nJsou ale užitečná – umožňují některé užitečné techniky, např. rekurzi.</p>\n<p>Jestli ti to celé připadá složité, dá se tomu zatím vyhnout dodržováním jednoho\npravidla:\n<em>nepřiřazuj ve funkcích do proměnných, které existují i vně funkce.</em>\n(Parametr funkce se počítá jako přiřazení.)</p>\n\n\n " } } }