Skip to content

Commit c222ab8

Browse files
committed
Split local variables from functions; add Recursion
1 parent 1f6e9b5 commit c222ab8

6 files changed

Lines changed: 314 additions & 92 deletions

File tree

courses/pyladies/info.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,8 @@ plan:
5959
slug: def-str
6060
materials:
6161
- lesson: beginners/def
62+
- lesson: beginners/local-variables
63+
- lesson: beginners/recursion
6264
- lesson: beginners/nested-traceback
6365
- lesson: beginners/str
6466
- lesson: beginners/str-index-slice

lessons/beginners/def/index.md

Lines changed: 0 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -204,95 +204,3 @@ def nic():
204204

205205
print(nic())
206206
```
207-
208-
209-
## Lokální proměnné
210-
211-
Gratuluji, umíš definovat vlastní funkce!
212-
Zbývá ještě vysvětlit jednu věc: lokální a globální proměnné.
213-
214-
Funkce může používat proměnné „zvnějšku“:
215-
216-
```python
217-
pi = 3.1415926
218-
219-
def obsah_kruhu(polomer):
220-
return pi * polomer ** 2
221-
222-
print(obsah_kruhu(100))
223-
```
224-
225-
Ale všechny argumenty a všechny proměnné, do kterých funkce přiřazuje,
226-
jsou *úplně nové* proměnné, které nemají nic
227-
společného s tím, co je „venku“ kolem funkce.
228-
229-
Těm úplně novým proměnným se říká
230-
*lokální proměnné* (angl. *local variables*), protože existují
231-
jen místně, v rámci volání jedné jediné funkce.
232-
Takže tohle nebude fungovat tak, jak se zdá:
233-
234-
```python
235-
x = 0
236-
237-
def nastav_x(hodnota):
238-
x = hodnota # Přiřazení do lokální proměnné!
239-
240-
nastav_x(40)
241-
print(x)
242-
```
243-
244-
245-
Proměnné, které nejsou lokální, jsou *globální* – ty
246-
existují v celém programu.
247-
(Jen ve funkcích, které mají náhodou
248-
lokální proměnnou stejného jména, „nejsou vidět“ –
249-
to jméno označuje lokální proměnnou.)
250-
251-
Pojďme si to ukázat.
252-
Než spustíš tenhle program,
253-
zkus předpovědět, co bude dělat.
254-
Pak ho pusť, a pokud dělal něco jiného,
255-
zkus vysvětlit proč.
256-
Pozor, je tam chyták!
257-
258-
```python
259-
from math import pi
260-
obsah = 0
261-
a = 30
262-
263-
def obsah_elipsy(a, b):
264-
obsah = pi * a * b # Přiřazení do `obsah`
265-
a = a + 3 # Přiřazení do `a`
266-
return obsah
267-
268-
print(obsah_elipsy(a, 20))
269-
print(obsah)
270-
print(a)
271-
```
272-
273-
Zkus odpovědět na tyto otázky:
274-
275-
* Je proměnná `pi` lokální, nebo globální?
276-
* Je proměnná `obsah` lokální, nebo globální?
277-
* Je proměnná `a` lokální, nebo globální?
278-
* Je proměnná `b` lokální, nebo globální?
279-
280-
{% filter solution %}
281-
* `pi` je globální – nepřiřazuje se do ní ve funkci;
282-
je „vidět“ v celém programu.
283-
* Proměnné `obsah` jsou v programu dvě – jedna globální,
284-
a jedna je lokální pro funkci `obsah_elipsy`,
285-
protože do ní tahle funkce přiřazuje.
286-
* Proměnné `a` jsou taky dvě, podobně jako `obsah`.
287-
Tady byl chyták: příkaz `a = a + 3` nemá žádný smysl;
288-
do `a` se sice uloží větší číslo, ale vzápětí funkce `obsah_elipsy` skončí
289-
a její lokální proměnná `a` přestane existovat.
290-
* Proměnná `b` je jenom lokální – jako argument funkce `obsah_elipsy`.
291-
292-
{% endfilter %}
293-
294-
295-
Jestli ti to celé připadá zmatené a složité, dá se tomu zatím vyhnout
296-
dodržováním jednoho pravidla:
297-
*nepřiřazuj ve funkcích do proměnných, které existují i vně funkce.*
298-
(Parametr funkce se počítá jako přiřazení.)
Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
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í.)
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
title: Lokální proměnné
2+
style: md
3+
attribution: Pro PyLadies Brno napsal Petr Viktorin, 2014-2017.
4+
license: cc-by-sa-40

0 commit comments

Comments
 (0)