|
| 1 | +# Lokální proměnné |
| 2 | + |
| 3 | +Už umíš definovat vlastní funkce. |
| 4 | +Zbývá ale ještě dovysvětlit, jak v nich fungují proměnné. |
| 5 | + |
| 6 | +Funkce může používat proměnné „zvnějšku“. |
| 7 | +Následující program přiřadí do proměnné `pi` a všechny další funkce |
| 8 | +mají k `pi` přístup: |
| 9 | + |
| 10 | +```python |
| 11 | +pi = 3.1415926 |
| 12 | + |
| 13 | +def obsah_kruhu(polomer): |
| 14 | + return pi * polomer ** 2 |
| 15 | + |
| 16 | +print(obsah_kruhu(100)) |
| 17 | +``` |
| 18 | + |
| 19 | +Jinak je tomu ale v případě, kdy proměnnou nastavíš *uvnitř* funkce. |
| 20 | + |
| 21 | +Všechny argumenty a všechny proměnné, do kterých funkce přiřazuje, |
| 22 | +jsou *úplně nové* proměnné, které nemají nic |
| 23 | +společného s tím, co je „venku“ kolem funkce. |
| 24 | + |
| 25 | +Těmto proměnným se říká *lokální proměnné* (angl. *local variables*), |
| 26 | +protože existují jen místně, v rámci volání jedné jediné funkce. |
| 27 | + |
| 28 | +Proměnné, které nejsou lokální, jsou *globální* – ty existují v celém programu. |
| 29 | + |
| 30 | +Pro příklad: |
| 31 | + |
| 32 | +```python |
| 33 | +def nastav_x(hodnota): |
| 34 | + x = hodnota # Přiřazení do lokální proměnné! |
| 35 | + |
| 36 | +nastav_x(40) |
| 37 | +print('x =', x) |
| 38 | +``` |
| 39 | + |
| 40 | +Program skončí s chybou! |
| 41 | +Funkce `nastav_x` si hraje na vlastním písečku; proměnná `x` je jen |
| 42 | +pro ni. |
| 43 | +Když funkce `nastav_x` skončí, proměnná `x` přestane existovat. |
| 44 | + |
| 45 | + |
| 46 | +## Přiřazení |
| 47 | + |
| 48 | +To, co dělá lokální proměnnou, je *přiřazení*. |
| 49 | +Porovnej `nastav_x` s příkladem na `obsah_kruhu` výše: rozdíl mezi `pi` a `x` |
| 50 | +je v tom, že do `x` funkce přiřazuje. |
| 51 | + |
| 52 | +Co je to přiřazení? Všechno, co *nastavuje* nějakou proměnnou. Například: |
| 53 | +* Klasika je přiřazovat pomocí `=`, např. `a = 3`. |
| 54 | +* Argumenty funkce: funkce `def nastav_x(hodnota)` přiřadí do `hodnota`, |
| 55 | +* Cyklus `for x in ...:` přiřazuje do proměnné `x`. |
| 56 | +* Pro úplnost, příkazy `def x(...):`, `import x` a `from ... import x` taky |
| 57 | + přiřazují do `x` – ale ve funkcích se moc nepoužívají. |
| 58 | + |
| 59 | +> [note] A další |
| 60 | +> K těmto materiálům se možná budeš vracet, tak pro úplnost přidám další |
| 61 | +> způsoby, které postupně poznáš. Není jich mnoho: |
| 62 | +> * Příkazy `with ... as x`, `del x`, `except ... as x` přiřazují do `x`. |
| 63 | +> * Přiřazují i speciální přiřazovací operátory jako `+=`, `*=`, `:=`. |
| 64 | +
|
| 65 | + |
| 66 | +## Zakrývání jména |
| 67 | + |
| 68 | +Jak to funguje, když ve funkci přiřadíš do proměnné, která existuje i globálně? |
| 69 | +Pak tu máme problém. |
| 70 | + |
| 71 | +Vytvoří se *úplně nová* lokální proměnná, která má stejné jméno jako |
| 72 | +ta globální. |
| 73 | +Jméno označuje lokální proměnnou, a ta globální pak „není vidět“. |
| 74 | + |
| 75 | +Tento příklad tedy nebude fungovat tak, jak se zdá: |
| 76 | + |
| 77 | +```python |
| 78 | +x = 0 |
| 79 | + |
| 80 | +def nastav_x(hodnota): |
| 81 | + x = hodnota # Přiřazení do lokální proměnné! |
| 82 | + print('Ve funkci nastav_x: x =', x) |
| 83 | + |
| 84 | +nastav_x(40) |
| 85 | +print('Venku: x =', x) |
| 86 | +``` |
| 87 | + |
| 88 | +V tomto programu existují *dvě* proměnné jménem `x`. |
| 89 | +Jedna je globální. Jedna je lokální pro funkci `nastav_x`. |
| 90 | +Jmenují se stejně, ale jsou to dvě různé proměnné. |
| 91 | + |
| 92 | + |
| 93 | +## Lokální nebo globální? |
| 94 | + |
| 95 | +Pojďme si to ukázat. |
| 96 | +Než spustíš tenhle program, zkus předpovědět, co bude dělat. |
| 97 | +Pak ho pusť, a pokud dělal něco jiného, zkus vysvětlit proč. |
| 98 | +Pozor na chytáky! |
| 99 | + |
| 100 | +```python |
| 101 | +from math import pi |
| 102 | +obsah = 0 |
| 103 | +a = 30 |
| 104 | + |
| 105 | +def obsah_elipsy(a, b): |
| 106 | + obsah = pi * a * b # Přiřazení do `obsah` |
| 107 | + a = a + 3 # Přiřazení do `a` |
| 108 | + return obsah |
| 109 | + |
| 110 | +print(obsah_elipsy(a, 20)) |
| 111 | +print(obsah) |
| 112 | +print(a) |
| 113 | +``` |
| 114 | + |
| 115 | +Zkus odpovědět na tyto otázky: |
| 116 | + |
| 117 | +* Je proměnná `pi` lokální, nebo globální? |
| 118 | +* Je proměnná `obsah` lokální, nebo globální? |
| 119 | +* Je proměnná `a` lokální, nebo globální? |
| 120 | +* Je proměnná `b` lokální, nebo globální? |
| 121 | +* Je proměnná `obsah_elipsy` lokální, nebo globální? |
| 122 | + |
| 123 | +{% filter solution %} |
| 124 | +* `pi` je globální – nepřiřazuje se do ní ve funkci; |
| 125 | + je „vidět“ v celém programu. |
| 126 | +* Proměnné `obsah` jsou v programu dvě – jedna globální, |
| 127 | + a jedna je lokální pro funkci `obsah_elipsy`, |
| 128 | + protože do ní tahle funkce přiřazuje. |
| 129 | +* Proměnné `a` jsou taky dvě, podobně jako `obsah`. |
| 130 | + Tady byl chyták: příkaz `a = a + 3` nemá žádný smysl; |
| 131 | + do `a` se sice uloží větší číslo, ale vzápětí funkce `obsah_elipsy` skončí |
| 132 | + a její lokální proměnná `a` přestane existovat. |
| 133 | +* Proměnná `b` je jenom lokální – jako argument funkce `obsah_elipsy`. |
| 134 | +* Proměnná `obsah_elipsy` je globální (a je v ní funkce). |
| 135 | + |
| 136 | +> [note] A pro úplnost |
| 137 | +> |
| 138 | +> * Klíčová slova `from`, `import`, `def`, `return` nejsou proměnné. |
| 139 | +> * Jméno modulu `math` není proměnná. |
| 140 | +> * Proměnná `print` se dá považovat za globální. |
| 141 | +> (Ve skutečnosti existuje zvláštní kategorie *zabudovaných* (angl. *builtin*) |
| 142 | +> proměnných.) |
| 143 | +
|
| 144 | +{% endfilter %} |
| 145 | + |
| 146 | + |
| 147 | +## Rada na závěr |
| 148 | + |
| 149 | +Pravidla pro lokální proměnné jsou pro začátečníky jednou z nejzvláštnějších |
| 150 | +věcí v Pythonu. |
| 151 | +Jsou ale užitečná – umožňují některé užitečné techniky, např. rekurzi. |
| 152 | + |
| 153 | +Jestli ti to celé připadá složité, dá se tomu zatím vyhnout dodržováním jednoho |
| 154 | +pravidla: |
| 155 | +*nepřiřazuj ve funkcích do proměnných, které existují i vně funkce.* |
| 156 | +(Parametr funkce se počítá jako přiřazení.) |
0 commit comments