diff --git a/courses/pyladies/info.yml b/courses/pyladies/info.yml
index 91720b809f..f29c51834c 100644
--- a/courses/pyladies/info.yml
+++ b/courses/pyladies/info.yml
@@ -100,10 +100,17 @@ plan:
materials:
- lesson: beginners/list
- lesson: beginners/tuple
+ - lesson: beginners/nested-list
- title: Tahák na seznamy
url: https://pyvec.github.io/cheatsheets/lists/lists-cs.pdf
type: cheatsheet
+- title: Iterujeme
+ slug: iteration
+ materials:
+ - lesson: beginners/range
+ - lesson: beginners/zip-enumerate
+
- title: Grafika
slug: pyglet
materials:
diff --git a/lessons/beginners/list/index.md b/lessons/beginners/list/index.md
index f51b69c8a2..06345f6f0c 100644
--- a/lessons/beginners/list/index.md
+++ b/lessons/beginners/list/index.md
@@ -1,27 +1,17 @@
-Tahle kapitola je plná nových věcí.
-Doufám, že vydržíš až do konce. A kdyby něco
-zatím nedávalo úplně smysl, nevěš hlavu:
-věci, které si teď vysvětlíme, se opravdu naučíš
-až v dalších lekcích, kde je budeme využívat
-prakticky.
-
Encyklopedické informace z této stránky shrnuje
[Tahák na seznamy](https://github.com/pyvec/cheatsheets/blob/master/lists/lists-cs.pdf),
-který si doporučuji vytisknout.
-
-Každý příklad v tomto textu si vyzkoušej;
-to, co Python vypíše, je důležitá součást lekce,
-i když v materiálech není přímo napsaná.
+který si můžeš vytisknout.
# Seznamy
Dnes si ukážeme, jak pracovat se *seznamy* (angl. *lists*).
-Doufám, že víš, kde máš na klávesnici hranaté
-závorky, protože právě těmi se seznamy vytváří:
+
+Začneme prakticky.
+Vytvoř si seznam pomocí následujícího kódu:
```python
-cisla = [1, 1, 2, 3, 5, 8, 13]
-print(cisla)
+zviratka = ['pes', 'kočka', 'králík']
+print(zviratka)
```
> [note]
@@ -30,204 +20,253 @@ print(cisla)
Seznam je hodnota, která může obsahovat spoustu dalších hodnot.
Tak jako řetězec obsahuje sekvenci znaků,
-seznam obsahuje sekvenci... čehokoliv. Třeba čísel.
-A tak jako můžeme pomocí cyklu `for`
-procházet řetězec po znacích,
-seznam můžeme procházet po jednotlivých prvcích:
+seznam obsahuje sekvenci jakýchkoli hodnot.
+V našem případě obsahuje sekvenci řetězců.
+
+A tak jako můžeš pomocí cyklu `for` procházet řetězec po znacích,
+seznam můžeš procházet po jednotlivých prvcích:
```python
-for cislo in cisla:
- print(cislo)
+for zviratko in zviratka:
+ print(zviratko)
```
-Seznamy se v programech vyskytují velice často:
-soubor se dá načíst jako seznam řetězců
-s jednotlivými řádky,
-seznam řetězců jako `'7♥'`
-a `'K♣'` může posloužit jako balíček karet,
-matematika je plná číselných řad,
-každá online služba má seznam uživatelů.
+Seznamy se v programech vyskytují často:
+soubor se dá načíst jako seznam řetězců s jednotlivými řádky,
+seznam řetězců jako `'7♥'` a `'K♣'` může posloužit jako balíček karet,
+matematika je plná číselných řad, e-shopy pracují se seznamy zboží.
+
+Hodnoty v seznamu můžou být jakéhokoli typu:
+```python
+prvni_prvocisla = [2, 3, 5, 7, 11]
+```
-Hodnoty v seznamu můžou být jakéhokoli typu,
-dokonce můžeme různé typy míchat v jednom seznamu
-(i když s takovými namixovanými seznamy se
-příliš často nesetkáme – více se používají v
-n-ticích, o kterých si povíme později):
+Dokonce můžeš různé typy míchat v jednom seznamu.
+(S takovými namixovanými seznamy se ovšem příliš často nesetkáš.
+Různé typy hodnot se používají spíš v n-ticích, o kterých si povíme
+později):
```python
seznam = [1, 'abc', True, None, range(10), len]
print(seznam)
```
-## Vybírání ze seznamů
+## Neměnitelné hodnoty
+
+Důležitá vlastnost seznamů je, že se dají *měnit*.
-Nejzákladnější operaci se seznamy,
-cyklus `for`, už jsme si ukázal{{gnd('i', 'y', both='i')}}.
-Druhá nejdůležitější operace je vybírání
-jednotlivých prvků.
-To funguje jako u řetězců: do hranatých závorek
-se dá číslo prvku. Čísluje se, jako u řetězců,
-od nuly; záporná čísla označují prvky od konce.
+Než vysvětlíme o co jde, připomeňme si jak fungují hodnoty, které se měnit
+nedají – např. čísla, řetězce, `True`/`False`/`None`.
+
+Vyzkoušej si následující kousek kódu. Co je na něm „špatně“?
```python
-print(cisla[2])
+kamaradka = 'Žaneta'
+print(kamaradka)
+kamaradka.upper()
+print(kamaradka)
```
-Hranatými závorkami můžeme získávat podseznamy.
-[Diagram z materiálů k řetězcům]({{ lesson_url('beginners/str')}}#slicing-diagram)
-ukazuje, jak u takového „sekání” číslovat:
-funguje to stejně, jen místo menšího řetězce
-dostaneme menší seznam.
+Proměnná `kamaradka` obsahuje řetězec `'Žaneta'` (který se už nedá změnit).
+Metoda `upper()` vytvoří a vrátí *nový* řetězec `'ŽANETA'`.
+Výsledná hodnota se ale v našem programu nevyužije – Python ji vypočítá,
+ale pak ji „zahodí“.
+
+Oprava je snadná: výsledek si ulož do proměnné.
+Často budeš chtít takový výsledek uložit zpátky do původní proměnné:
```python
-print(cisla[2:-3])
+kamaradka = kamaradka.upper()
```
-## Měnění seznamů
+Tímto přiřazením Python „zahodí“ původní hodnotu,
+a od tohoto příkazu dál bude proměnná `kamaradka` označovat nový řetězec.
-Důležitá vlastnost seznamů, kterou nemají ani čísla, ani řetězce
-(a `True`/`False`/`None` už vůbec ne), je,
-že seznamy se dají měnit.
+Podobně by se dala proměnná přenastavit na jakoukoli jinou hodnotu:
-Čísla měnit nejdou – máš-li `a = 3` a
-napíšeš `a = a + 1`, číslo `3` se nezmění.
-Vypočítá se nové číslo `4` a proměnná `a`
-se nastaví na toto nové číslo.
+```python
+kamaradka = 'Žaneta'
+print(kamaradka)
+kamaradka = 'Alexandra'
+print(kamaradka)
+```
+
+
+## Měnění seznamů
+
+A jak jsou na tom seznamy?
+Ty se měnit dají.
-Oproti tomu seznamy se dají měnit bez nastavování proměnné.
Základní způsob, jak změnit seznam, je přidání
prvku na konec pomocí metody `append`.
-Ta *nic nevrací* (resp. vrací `None`),
-ale „na místě” (angl. *in place*) změní
-seznam, na kterém pracuje. Vyzkoušej si to:
+Ta *nic nevrací* (resp. vrací `None`), ale „na místě” (angl. *in place*) změní
+seznam, se kterým pracuje. Vyzkoušej si to:
-```python
-prvocisla = [2, 3, 5, 7, 11, 13, 17]
-print(prvocisla)
-prvocisla.append(19)
-print(prvocisla)
+```pycon
+>>> zviratka = ['pes', 'kočka', 'králík']
+>>> print(zviratka)
+['pes', 'kočka', 'králík']
+>>> zviratka.append('morče')
+>>> print(zviratka)
+['pes', 'kočka', 'králík', 'morče']
```
-Takové měnění hodnoty může být občas překvapující,
-protože stejnou hodnotu může mít více proměnných.
+Všimni si, že proměnná `zviratka` se nastavuje jen na začátku.
+V rámci celého běhu programu výše existuje jen jeden seznam.
+Na začátku má tři prvky, pak mu jeden přibude, ale stále je to jeden a ten
+samý seznam.
+
+Takové měnění může být občas překvapující,
+protože stejná hodnota může být přiřazená ve více proměnných.
Protože se mění hodnota samotná, může to vypadat,
-že se proměnná „mění aniž na ni sáhneme”:
+že se „mění proměnná, aniž na ni sáhneš”:
```python
-a = [1, 2, 3] # vytvoření seznamu
-b = a # tady se nový seznam nevytváří
+a = [1, 2, 3] # Vytvoření seznamu
+b = a # Tady se nový seznam nevytváří!
# seznam vytvořený v prvním řádku má teď dvě jména: "a" a "b",
-# ale stále pracujeme jenom s jedním seznamem
+# ale stále pracuješ jenom s jedním seznamem
print(b)
a.append(4)
print(b)
```
+
## Další způsoby, jak měnit seznamy
-Kromě metody `append`, která přidává
-jediný prvek, existuje metoda `extend`,
-která umí přidávat prvků víc.
-Prvky k přidání jí předáme ve formě seznamu:
+Kromě metody `append`, která přidává jediný prvek na konec, existuje
+spousta dalších metod, které seznamy mění.
+Všechny udělají změny přímo v daném seznamu a (kromě `pop`) vrací `None`:
+
+* `extend()` přidá více prvků najednou,
+* `insert()` přidá prvek na danou pozici,
+* `pop()` odebere poslední prvek a *vrátí ho* (jako návratovou hodnotu),
+* `remove()` odstraní první výskyt daného prvku,
+* `sort()` seznam seřadí (řetězce podle “abecedy”, čísla vzestupně),
+* `reverse()` obrátí pořadí prvků,
+* `clear()` odstraní všechny prvky.
+
+{{ figure(img=static('methods.svg'), alt="Tahák") }}
+
+Například:
```python
-dalsi_prvocisla = [23, 29, 31]
-prvocisla.extend(dalsi_prvocisla)
-print(prvocisla)
+zviratka = ['pes', 'kočka', 'králík']
+zviratka.append('morče') # ['pes', 'kočka', 'králík', 'morče']
+zviratka.insert(2, 'had') # ['pes', 'kočka', 'had', 'králík', 'morče']
+zviratka.pop() # ['pes', 'kočka', 'had', 'králík'], vrátí 'morče'
+zviratka.remove('had') # ['pes', 'kočka', 'králík']
+zviratka.sort() # ['kočka', 'králík', 'pes']
+zviratka.reverse() # ['pes', 'králík', 'kočka']
+zviratka.clear() # []
```
-Metoda `extend` umí pracovat i s jinými
-typy než se seznamy – ráda zpracuje cokoli, přes
-co umí cyklit `for`: např.
-jednotlivé znaky řetězců, řádky souborů, nebo čísla z `range()`.
+## Vybírání ze seznamů
+
+Často budeš ze seznamu chtít vybrat prvek na určité pozici.
+To funguje jako u řetězců: do hranatých závorek dáš číslo prvku.
+Stejně jako u řetězců se čísluje od nuly a záporná čísla číslují od konce.
```python
-seznam = []
-seznam.extend('abcdef')
-seznam.extend(range(10))
-print(seznam)
+zviratka = ['pes', 'kočka', 'králík']
+print(zviratka[2])
```
-## Měnění prvků
+Hranatými závorkami můžeš získat i podseznam.
+[Diagram z materiálů k řetězcům]({{ lesson_url('beginners/str-index-slice')}}#slicing-diagram)
+ukazuje, jak u takového „sekání” číslovat:
+funguje to stejně, jen místo menšího řetězce dostaneš menší seznam.
+
+```python
+print(zviratka[2:-3])
+```
+
+„Sekáním“ vzniká nový seznam – když pak ten původní změníš, v novém menším seznamu se
+to neprojeví.
+
-Ale dost přidávání.
-Seznamům se dají i měnit jednotlivé prvky
-a to jednoduše tak, že do prvku přiřadíme,
-jako by to byla proměnná:
+### Měnění prvků
+
+Na rozdíl od řetězců (které se měnit nedají) můžeš u existujících seznamů
+nastavovat konkrétní prvky – a to tak, že do prvku přiřadíš jako by to byla
+proměnná:
```python
-cisla = [1, 0, 3, 4]
-cisla[1] = 2
-print(cisla)
+zviratka = ['pes', 'kočka', 'králík']
+zviratka[1] = 'koťátko'
+print(zviratka)
```
Přiřazovat se dá i do podseznamu – v tomto případě
se podseznam nahradí jednotlivými prvky z toho,
-co přiřazujeme.
-Jako u `extend` můžeš do podseznamu opět přiřadit cokoli, co umí
-zpracovat `for` – seznam, řetězec, `range()` apod.
+co přiřadíš.
```python
-cisla = [1, 2, 3, 4]
-cisla[1:-1] = [6, 5]
-print(cisla)
+zviratka = ['pes', 'kočka', 'králík', 'had', 'andulka']
+print(zviratka[1:-1])
+zviratka[1:-1] = ['koťátko', 'králíček', 'hádě']
+print(zviratka)
```
-## Mazání prvků
+### Mazání prvků
-Přiřazením do podseznamu se dá i změnit délka
-seznamu, nebo některé prvky úplně odstranit:
+Přiřazením do podseznamu můžeš i změnit délku
+seznamu nebo některé prvky úplně odstranit:
```python
-cisla = [1, 2, 3, 4]
-cisla[1:-1] = [0, 0, 0, 0, 0, 0]
-print(cisla)
-cisla[1:-1] = []
-print(cisla)
+zviratka = ['pes', 'kočka', 'králík']
+zviratka[1:-1] = ['had', 'ještěrka', 'drak']
+print(zviratka)
+zviratka[1:-1] = []
+print(zviratka)
```
-Tenhle zápis pro mazání prvků je ale docela
-nepřehledný, a proto na to máme zvláštní příkaz
-jménem `del`.
+Tenhle zápis pro mazání prvků je ale docela nepřehledný.
+Proto na to existuje zvláštní příkaz jménem `del`.
Jak už jeho název (z angl. *delete*, smazat)
napovídá, smaže, co mu přijde pod ruku – jednotlivé
prvky seznamů, podseznamy, … a dokonce i proměnné!
+Zkus si:
```python
-cisla = [1, 2, 3, 4, 5, 6]
-del cisla[-1]
-print(cisla)
-del cisla[3:5]
-print(cisla)
-del cisla
-print(cisla)
+zviratka = ['pes', 'kočka', 'králík', 'had', 'ještěrka', 'andulka']
+
+print(zviratka[-1])
+del zviratka[-1]
+print(zviratka)
+
+print(zviratka[1:-1])
+del zviratka[1:-1]
+print(zviratka)
+
+del zviratka
+print(zviratka)
```
-Další mazací metody jsou:
-* `pop`, která odstraní *a vrátí* poslední prvek v seznamu – například pokud
- mám seznam karet v balíčku, jde takhle jednoduše „líznout” kartu,
-* `remove`, která najde v seznamu daný prvek a odstraní ho,
-* `clear`, která vyprázdní celý seznam.
+Na mazání prvků můžeš použít i metody zmíněné výše:
+* `pop` odstraní poslední prvek v seznamu a *vrátí* ho,
+* `remove` najde v seznamu první výskyt daného prvku a odstraní ho,
+* `clear` vyprázdní celý seznam.
```python
-cisla = [1, 2, 3, 'abc', 4, 5, 6, 12]
-posledni = cisla.pop()
-print(posledni)
-print(cisla)
+balicek = ['eso', 'sedma', 'svršek', 'sedma', 'král']
+liznuta_karta = karty.pop()
+print(liznuta_karta)
+print(balicek)
-cisla.remove('abc')
-print(cisla)
+balicek.remove('sedma')
+print(balicek)
-cisla.clear()
-print(cisla)
+balicek.clear()
+print(balicek)
```
## Řazení
-A taky tu máme metodu `sort`, která prvky seznamu seřadí.
+Metoda `sort` seřadí prvky seznamu.
```python
seznam = [4, 7, 8, 3, 5, 2, 4, 8, 5]
@@ -236,16 +275,14 @@ print(seznam)
```
Aby se daly seřadit, musí být prvky seznamu vzájemně
-*porovnatelné* – konktrétně na ně musí fungovat
-operátor `<`.
+*porovnatelné* – konktrétně na ně musí fungovat operátor `<`.
Seznam s mixem čísel a řetězců tedy seřadit nepůjde.
-Operátor `<` definuje i
-jak přesně se řadí (např. čísla podle velikosti;
-řetězce podle speciální „abecedy” která řadí
-velká písmena za malá, česká až za anglická, atd.).
+Operátor `<` definuje i jak přesně `sort` řadí: čísla vzestupně podle
+velikosti; řetězce podle speciální „abecedy” která řadí
+velká písmena za malá, česká až za anglická, atd.
-Metoda `sort` zná pojmenovaný argument
-`reverse`. Pokud ho nastavíš na *True*, řadí se „naopak”.
+Metoda `sort` zná pojmenovaný argument `reverse`.
+Pokud ho nastavíš na *True*, řadí se naopak – od největšího prvku po nejmenší.
```python
seznam = [4, 7, 8, 3, 5, 2, 4, 8, 5]
@@ -255,7 +292,7 @@ print(seznam)
## Známé operace se seznamy
-Spousta toho, co můžeme dělat s řetězci, má stejný
+Spousta toho, co můžeš dělat s řetězci, má stejný
účinek i u seznamů.
Třeba sečítání a násobení číslem:
@@ -264,7 +301,7 @@ melodie = ['C', 'E', 'G'] * 2 + ['E', 'E', 'D', 'E', 'F', 'D'] * 2 + ['E', 'D',
print(melodie)
```
-Stejně jako u řetězců, sečítat jde jen seznam
+Stejně jako u řetězců jde sečítat jen seznam
se seznamem – ne třeba seznam s řetězcem.
Další staří známí jsou funkce `len`,
@@ -280,8 +317,8 @@ print('D' in melodie) # Je 'D' v seznamu?
Poslední tři se ale přece jen chovají kapku jinak:
u řetězců pracují s *podřetězci*,
u seznamů jen s *jednotlivými* prvky.
-Takže ačkoliv naše melodie obsahuje prvky
-`'D'` a `'E'` vedle sebe, `'DE'` v seznamu není:
+Takže ačkoliv melodie výše obsahuje prvky
+`'D'` a `'E'` vedle sebe, `'DE'` ani `['D', 'E']` v seznamu není:
```python
print('DE' in melodie)
@@ -291,7 +328,7 @@ print(melodie.index('DE'))
## Seznam jako podmínka
-Seznam se dá použít v příkazu `if` (nebo `while`) jako podmínka,
+Seznam můžeš použít v příkazu `if` (nebo `while`) jako podmínku,
která platí, když v tom seznamu něco je.
Jinými slovy, `seznam` je tu „zkratka“ pro `len(seznam) > 0`.
@@ -302,19 +339,17 @@ else:
print('Seznam je prázdný!')
```
-Podobně se dají v podmínce použít i řetězce.
+Podobně můžeš v podmínce použít i řetězce.
A dokonce i čísla – ta jako podmínka platí, pokud jsou nenulová.
## Tvoření seznamů
Tak jako funkce `int` převádí na
celá čísla a `str` na řetězce,
-funkce `list` (angl. *seznam*) převádí na seznam.
-Jako argument jí předáme jakoukoli hodnotu,
+funkce `list` převádí na seznam.
+Jako argument jí můžeš předat jakoukoli hodnotu,
kterou umí zpracovat příkaz `for`.
-Z řetězců udělá seznam znaků, z otevřeného souboru
-udělá seznam řádků, z `range` udělá
-seznam čísel.
+Z řetězce udělá seznam znaků, z `range` udělá seznam čísel.
```python
abeceda = list('abcdefghijklmnopqrstuvwxyz')
@@ -324,8 +359,7 @@ print(cisla)
```
I ze seznamu udělá funkce `list` seznam.
-To může znít zbytečně, ale není – vytvoří se
-totiž *nový* seznam.
+To může znít zbytečně, ale není – vytvoří se totiž *nový* seznam.
Bude mít sice stejné prvky ve stejném pořadí,
ale nebude to ten samý seznam:
měnit se bude nezávisle na tom starém.
@@ -337,13 +371,14 @@ b = list(a)
print(b)
a.append(4)
print(b)
+print(a)
```
Další způsob, jak tvořit seznamy
(zvláště složitější), je nejdřív udělat prázdný
seznam a pak ho postupně naplnit pomocí funkce `append`.
Třeba pokud z nějakého důvodu chceš seznam
-mocnin dvou, projdi čísla, kterými chceme mocnit,
+mocnin dvou, projdi čísla, kterými chceš mocnit,
cyklem `for` a pro každé z nich
do seznamu přidej příslušnou mocninu:
@@ -354,25 +389,54 @@ for cislo in range(10):
print(mocniny_dvou)
```
+Podobným způsobem získáš seznam seznam `matka`, `babička`, `prababička`,
+`praprababička`, atd.:
+
+```python
+predkove = ['matka']
+for pocet_pra in range(10):
+ predkove.append(('pra' * pocet_pra) + 'babička')
+print(predkove)
+```
+
Chceš-li seznam, který reprezentuje balíček karet,
-zavolej `append` pro všechny kombinace barev a hodnot.
+zavolej `append` pro všechny kombinace barev a hodnot:
```python
balicek = []
-for barva in '♠', '♥', '♦', '♣': # (Na Windows použij textová jména)
- for hodnota in list(range(2, 11)) + ['J', 'Q', 'K', 'A']:
- balicek.append(str(hodnota) + barva)
+for barva in '♠', '♥', '♦', '♣':
+ for hodnota in ['2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K', 'A']:
+ balicek.append(hodnota + barva)
print(balicek)
```
+> [note] Jde to líp?
+> Psát do programu výčet po sobě jdoucích čísel,
+> `'2', '3', '4', '5', '6', '7', '8', '9', '10'`,
+> není ideální – na takovou otročinu přece máme počítače!
+> Zkus čísla dostat pomocí `range`.
+> Ale pozor, není to úplně přímočaré:
+>
+> * Jaké argumenty dáš funkci `range`, abys dostal{{a}} čísla od 2 do 10?
+> * Funkce `range` vrací sekvenci, která ale není seznam.
+> Abys ji mohl{{a}} spojit se seznamem `['J', 'Q', 'K', 'A']`, budeš ji muset
+> na seznam převést: `list(range(...))`
+> * Abys mohl{{a}} čísla z `range` připojit k řetězci jako `♠`, budeš muset
+> každou hodnotu před použitím převést na řetězec: `str(hodnota)`.
+>
+> Bonus: Jaký je nejkratší zápis, kterým můžeš zadat seznam
+> `['J', 'Q', 'K', 'A']`?
+>
+> Řešení najdeš v textu o kousek níže.
+
+
## Seznamy a řetězce
-Seznamy a řetězce jsou druhy „sekvencí”,
-takže snad nepřekvapí, že se dá různě převádět
-z jednoho typu na druhý.
-Funkce `list` vytvoří z řetězce
-seznam znaků.
-Když chceme dostat seznam slov, použijeme
+Seznamy a řetězce jsou druhy *sekvencí*.
+Můžeš různě převádět z jednoho typu na druhý.
+
+Funkce `list` vytvoří z řetězce seznam znaků.
+Když chceš dostat seznam slov, použij
na řetězci metodu `split` (angl. *rozdělit*):
```python
@@ -381,119 +445,45 @@ print(slova)
```
Metoda `split` umí brát i argument.
-Pokud ho předáme, místo mezer (a nových řádků)
-se řetězec „rozseká” daným oddělovačem.
-Takže když máme nějaká data oddělená čárkami,
-není nic jednoduššího než použít `split` s čárkou:
+Pokud ho předáš, řetězec „rozseká” daným oddělovačem
+(místo mezer a nových řádků).
+Takže když máš nějaká data oddělená čárkami,
+použíj `split` s čárkou:
```python
zaznamy = '3A,8B,2E,9D'.split(',')
print(zaznamy)
```
-Chceme-li spojit seznam řetězců zase dohromady
-do jediného řetězce, použijeme metodu
-`join` (angl. *spojit*).
+Chceš-li spojit seznam řetězců zase dohromady
+do jediného řetězce, použij metodu `join` (angl. *spojit*).
Pozor, tahle metoda se volá na *oddělovači*,
-tedy řetězci, kterým se jednotlivé kousky „slepí”
-dohromady; a jako argument bere seznam jednotlivých
-řetězců.
+tedy na řetězci, kterým se jednotlivé kousky „slepí” dohromady.
+Seznam jednotlivých řetězců bere jako argument.
```python
veta = ' '.join(slova)
print(veta)
```
-## Úkol
-
-Představ si, že ti uživatelé zadávají jména a příjmení a ty si je ukládáš do
-seznamu pro další použití např. v evidenci studentů. Ne všichni jsou ale pořádní,
-a tak se v seznamu sem tam objeví i jméno s nesprávně zadanými velkými písmeny.
-Například:
-
-```python
-zaznamy = ['pepa novák', 'Jiří Sládek', 'Ivo navrátil', 'jan Poledník']
-```
-
-Úkolem je:
-
-* Napsat funkci, která vybere jen ty správně zadané záznamy, které mají správně
-jméno i příjmení s velkým počátečním písmenem.
-* Napsat funkci, která vybere naopak jen ty nesprávně zadané záznamy.
-* *(Nepovinný)* – Napsat funkci, která vrátí seznam s opravenými záznamy.
-
-Výsledné funkce by měly fungovat takto:
-
-```python
-zaznamy = ['pepa novák', 'Jiří Sládek', 'Ivo navrátil', 'jan Poledník']
-
-chybne_zaznamy = vyber_chybne(zaznamy)
-print(chybne_zaznamy) # → ['pepa novák', 'Ivo navrátil', 'jan Poledník']
-
-spravne_zaznamy = vyber_spravne(zaznamy)
-print(spravne_zaznamy) # → ['Jiří Sládek']
-
-opravene_zaznamy = oprav_zaznamy(zaznamy)
-print(opravene_zaznamy) # → ['Pepa Novák', 'Jiří Sládek', 'Ivo Navrátil', 'Jan Poledník']
-```
-
-> [note]
-> Snadný způsob jak zjistit, zda je řetězec složen jen z malých písmen,
-> je metoda `islower()`, která vrací True, pokud řetězec obsahuje jen malá
-> písmena, jinak vrací False. Například `'abc'.islower() == True` ale
-> `'aBc'.islower() == False`.
->
-> Snadný způsob jak převést první písmenko na velké je metoda `capitalize()`:
-> např. `'abc'.capitalize() == 'Abc'`
-
-{% filter solution %}
-```python
-def vyber_chybne(seznam):
- vysledek = []
- for zaznam in seznam:
- jmeno_a_prijmeni = zaznam.split(' ')
- jmeno = jmeno_a_prijmeni[0]
- prijmeni = jmeno_a_prijmeni[1]
- if jmeno[0].islower() or prijmeni[0].islower():
- vysledek.append(zaznam)
- return vysledek
-
-def vyber_spravne(seznam):
- vysledek = []
- for zaznam in seznam:
- jmeno_a_prijmeni = zaznam.split(' ')
- jmeno = jmeno_a_prijmeni[0]
- prijmeni = jmeno_a_prijmeni[1]
- if not jmeno[0].islower() and not prijmeni[0].islower():
- vysledek.append(zaznam)
- return vysledek
-
-def oprav_zaznamy(seznam):
- vysledek = []
- for zaznam in seznam:
- jmeno_a_prijmeni = zaznam.split(' ')
- jmeno = jmeno_a_prijmeni[0]
- prijmeni = jmeno_a_prijmeni[1]
- vysledek.append(jmeno.capitalize() + ' ' + prijmeni.capitalize())
- return vysledek
-```
-{% endfilter %}
-
## Seznamy a náhoda
-Modul `random` obsahuje dvě funkce, které se hodí k seznamům.
-Jako `random.randrange`, obě mají něco
-společného s náhodou.
+Modul `random` obsahuje funkce, které mají něco společného s náhodou:
+třeba nám už známou `random.randrange`.
+Podívejme se na dvě další, které se hodí k seznamům.
Funkce `shuffle` seznam „zamíchá” – všechny prvky náhodně popřehází.
-Jako metoda `sort` i funkce `shuffle` nic nevrací.
+Seznam změní „na místě“ a nic nevrací (podobně jako metoda `sort`).
```python
import random
+ciselne_hodnoty = list(range(2, 11))
+pismenne_hodnoty = list('JQKA')
+
balicek = []
for barva in '♠', '♥', '♦', '♣':
- for hodnota in list(range(2, 11)) + ['J', 'Q', 'K', 'A']:
+ for hodnota in ciselne_hodnoty + pismenne_hodnoty:
balicek.append(str(hodnota) + barva)
print(balicek)
@@ -502,86 +492,12 @@ print(balicek)
```
A funkce `choice` ze seznamu vybere jeden náhodný prvek.
-S použitím seznamu tak můžeme výrazně zjednodušit
-úvodní část naší staré hry kámen/nůžky/papír:
+S použitím seznamu tak můžeš třeba jednoduše vybrat tah pro hru
+kámen/nůžky/papír:
```python
import random
mozne_tahy = ['kámen', 'nůžky', 'papír']
tah_pocitace = random.choice(mozne_tahy)
+print(tah_pocitace)
```
-
-## Vnořené seznamy
-
-A perlička na konec!
-Na začátku tohoto textu je napsáno, že seznam
-může obsahovat jakýkoli typ hodnot.
-Může třeba obsahovat i další seznamy:
-
-```python
-seznam_seznamu = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
-```
-
-Takový seznam se chová docela normálně – jdou
-z něj třeba brát jednotlivé prvky
-(které jsou ovšem taky seznamy):
-
-```python
-prvni_seznam = seznam_seznamu[0]
-print(prvni_seznam)
-```
-
-A protože jsou prvky samy seznamy,
-můžeme mluvit o věcech jako „první prvek druhého seznamu”:
-
-```python
-druhy_seznam = seznam_seznamu[1]
-prvni_prvek_druheho_seznamu = druhy_seznam[0]
-print(prvni_prvek_druheho_seznamu)
-```
-
-A protože výraz `seznam_seznamu[1]`
-označuje seznam, můžeme brát prvky přímo z něj:
-
-```python
-prvni_prvek_druheho_seznamu = (seznam_seznamu[1])[0]
-```
-
-Neboli:
-
-```python
-prvni_prvek_druheho_seznamu = seznam_seznamu[1][0]
-```
-
-A má tahle věc nějaké použití, ptáš se?
-Stejně jako vnořené cykly `for`
-nám umožnily vypsat tabulku, vnořené seznamy
-nám umožní si tabulku „zapamatovat”.
-
-```python
-def vytvor_tabulku(velikost=11):
- seznam_radku = []
- for a in range(velikost):
- radek = []
- for b in range(velikost):
- radek.append(a * b)
- seznam_radku.append(radek)
- return seznam_radku
-
-nasobilka = vytvor_tabulku()
-
-print(nasobilka[2][3]) # dva krát tři
-print(nasobilka[5][2]) # pět krát dva
-print(nasobilka[8][7]) # osm krát sedm
-
-# Vypsání celé tabulky
-for radek in nasobilka:
- for cislo in radek:
- print(cislo, end=' ')
- print()
-```
-
-Co s takovou „zapamatovanou” tabulkou?
-Můžeš si do ní uložit třeba pozice
-figurek na šachovnici nebo křížků a koleček
-ve *2D* piškvorkách.
diff --git a/lessons/beginners/list/static/methods.svg b/lessons/beginners/list/static/methods.svg
new file mode 100644
index 0000000000..2c67d7dde8
--- /dev/null
+++ b/lessons/beginners/list/static/methods.svg
@@ -0,0 +1,1305 @@
+
+
diff --git a/lessons/beginners/nested-list/index.md b/lessons/beginners/nested-list/index.md
new file mode 100644
index 0000000000..588a457771
--- /dev/null
+++ b/lessons/beginners/nested-list/index.md
@@ -0,0 +1,78 @@
+# Vnořené seznamy
+
+Seznam může obsahovat jakýkoli typ hodnot: čísla, řetězce a tak dále:
+
+```python
+prvocisla = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41]
+zviratka = ['pes', 'kočka', 'králík']
+odpovedi = [False, False, False, True, False, True, True]
+```
+
+Stejně tak může seznam obsahovat i další seznamy.
+Podobně jako seznam čísel nebo seznam řetězců tak lze vytvořit seznam seznamů:
+
+```python
+seznam_seznamu = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
+```
+
+Takový seznam se chová docela normálně – můžeš z něj třeba brát jednotlivé
+prvky (které jsou ovšem taky seznamy):
+
+```python
+prvni_seznam = seznam_seznamu[0]
+print(prvni_seznam)
+```
+
+A protože jsou prvky samy seznamy,
+dá se mluvit o věcech jako „první prvek druhého seznamu”:
+
+```python
+druhy_seznam = seznam_seznamu[1]
+prvni_prvek_druheho_seznamu = druhy_seznam[0]
+print(prvni_prvek_druheho_seznamu)
+```
+
+A protože výraz `seznam_seznamu[1]`
+označuje seznam, můžeš brát prvky přímo z něj:
+
+```python
+prvni_prvek_druheho_seznamu = (seznam_seznamu[1])[0]
+```
+
+Neboli:
+
+```python
+prvni_prvek_druheho_seznamu = seznam_seznamu[1][0]
+```
+
+A má tahle věc nějaké použití?
+Stejně jako vnořené cykly `for` ti umožnily vypsat tabulku, vnořené seznamy
+ti umožní si tabulku „zapamatovat”.
+
+```python
+def vytvor_tabulku(velikost=11):
+ seznam_radku = []
+ for a in range(velikost):
+ radek = []
+ for b in range(velikost):
+ radek.append(a * b)
+ seznam_radku.append(radek)
+ return seznam_radku
+
+nasobilka = vytvor_tabulku()
+
+print(nasobilka[2][3]) # dva krát tři
+print(nasobilka[5][2]) # pět krát dva
+print(nasobilka[8][7]) # osm krát sedm
+
+# Vypsání celé tabulky
+for radek in nasobilka:
+ for cislo in radek:
+ print(cislo, end=' ')
+ print()
+```
+
+Co s takovou „zapamatovanou” tabulkou?
+Můžeš si do ní uložit třeba pozice
+figurek na šachovnici nebo křížků a koleček
+ve *2D* piškvorkách.
diff --git a/lessons/beginners/nested-list/info.yml b/lessons/beginners/nested-list/info.yml
new file mode 100644
index 0000000000..7167651c4a
--- /dev/null
+++ b/lessons/beginners/nested-list/info.yml
@@ -0,0 +1,4 @@
+title: Vnořené seznamy
+style: md
+attribution: Pro PyLadies Brno napsal Petr Viktorin, 2014-2020.
+license: cc-by-sa-40
diff --git a/lessons/beginners/range/index.md b/lessons/beginners/range/index.md
new file mode 100644
index 0000000000..53b52e3bd3
--- /dev/null
+++ b/lessons/beginners/range/index.md
@@ -0,0 +1,131 @@
+# Range – sekvence čísel
+
+Funkce `range(10)` vrátí speciální hodnotu,
+která v sobě obsahuje čísla od 0 do 9:
+
+```pycon
+>>> sekvence = range(10)
+>>> sekvence
+range(0, 10)
+```
+
+Je to hodnota typu `range`, podobně jako čísla jsou typu `int`, řetězce typu
+`str`, nebo seznamy typu `list`.
+
+Chceš-li se podívat, co v tomhle `range(0, 10)` vlastně je, máš dvě základní
+možnosti – projít ho cyklem `for` nebo převést na seznam konkrétních čísel:
+
+```pycon
+>>> sekvence
+range(0, 10)
+>>> for i in sekvence:
+... print(i)
+0
+1
+2
+3
+4
+5
+6
+7
+8
+9
+>>> list(sekvence)
+[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
+```
+
+Možná se ptáš – proč tak složitě?
+Proč se místo `range(0, 10)` prostě ta čísla neukážou rovnou?
+
+Je to proto, že `range` se dá použít na opravdu dlouhé řady čísel:
+
+```pycon
+>>> range(10000)
+range(0, 10000)
+>>> list(range(10000))
+[0, 1, 2, 3, ..., 9999]
+```
+
+Kdybys zkusil{{a}} třeba `list(range(1000000000000000))`, počítači
+dojde paměť.
+Biliarda čísel se tam prostě nevejde.
+Python vyhodí výjimku `MemoryError`.
+
+
+> [warning]
+> Pokud máš na počítači v jiném okně neuloženou práci, radši `list(range(...))`
+> s hodně vysokými čísly nezkoušej.
+>
+> U absurdně vysokého čísla jako `1000000000000000` Python předem ví,
+> že mu paměť dojde, a tak ohlásí chybu ještě než se bude snažit seznam vytvořit.
+> U trochu menšího čísla (např. `1000000000`, ale na každém počítači je to
+> jinak) se může stát, že se Python pokusí seznam začít tvořit, zaplní přitom
+> většinu dostupné paměti a počítač „zamrzne“.
+> V závislosti na systému se pak třeba může stát že reakce na
+> Ctrl+C bude trvat hodně dlouho.
+
+Se samotným `range(1000000000000000)` ale není problém.
+S konceptem *všech čísel od 0 do biliardy* se počítač vypořádá, i když si je
+neumí „zapamatovat“ všechny *najednou*.
+
+Je spousta věcí, které Python umí s `range` udělat, aniž by potřeboval
+„spočítat“ každé z čísel.
+Spousta operací, které znáš od seznamů, bude fungovat i s `range`:
+
+```pycon
+>>> zajimava_cisla = range(8, 10000, 3) # Každé třetí číslo od 8 do 9999
+>>> zajimava_cisla[80] # Osmdesáté "zajímavé číslo"
+248
+>>> zajimava_cisla[:5] # Prvních 5 "zajímavých čísel"
+range(8, 23, 3)
+>>> list(zajimava_cisla[:5]) # Vypsání prvních 5 "zajímavých čísel"
+[8, 11, 14, 17, 20]
+>>> len(zajimava_cisla) # Kolik tam je čísel?
+3331
+>>> 1337 in zajimava_cisla # Je v této sekvenci moje konkrétní číslo ?
+True
+>>> zajimava_cisla.index(1337) # Kolikáté je?
+443
+```
+
+```pycon
+>>> import random
+>>> random.choice(zajimava_cisla)
+1229
+```
+
+```pycon
+>>> for i in zajimava_cisla:
+... print(i)
+... if i > 20:
+... break # Stačilo!
+8
+11
+14
+17
+20
+23
+```
+
+Objekt `range` ale nejde měnit – mazání prvků nebo metody jako
+`zajimava_cisla.sort()`, `zajimava_cisla.pop()` fungovat nebudou.
+
+> [note] Proč ne?
+> Když máš objekt jako `range(8, 10000, 3)`, osmdesátý prvek je jen trocha
+> matematiky: spočítáš `8 + 3 * 80` a zkontroluješ že to nepřesáhlo `10000`.
+> Podobně je to s ostatními sekvencemi „všech X-tých čísel od
+> A do B“, tedy s ostatními `range`.
+>
+> Kdyby ale šlo udělat něco jako:
+>
+> ```python
+> sekvence = range(8, 10000, 3)
+> del sekvence[10]
+> sekvence.insert(103, 'ježek')
+> ```
+>
+> … jde najednou o mnohem složitější koncept, kde se N-tý prvek hledá mnohem
+> hůř. Už to není jednoduchá sekvence čísel – už to není `range`, ale spíš
+> seznam jakýchkoli hodnot.
+
+Pokud budeš něco, co `range` neumí, potřebovat, převeď `range` na seznam.
diff --git a/lessons/beginners/range/info.yml b/lessons/beginners/range/info.yml
new file mode 100644
index 0000000000..10fbe5ccee
--- /dev/null
+++ b/lessons/beginners/range/info.yml
@@ -0,0 +1,4 @@
+title: Range - sekvence čísel
+style: md
+attribution: Pro PyLadies Brno napsal Petr Viktorin, 2019.
+license: cc-by-sa-40
diff --git a/lessons/beginners/tuple/index.md b/lessons/beginners/tuple/index.md
index eec9cfeafc..0d34379bff 100644
--- a/lessons/beginners/tuple/index.md
+++ b/lessons/beginners/tuple/index.md
@@ -3,39 +3,45 @@
Když už známe seznam, podívejme se na jeho sestřičku: takzvanou
n-tici (angl. *tuple*).
-N-tice, podobně jako seznam,
-může obsahovat n prvků.
+N-tice může, podobně jako seznam, obsahovat n prvků.
N-tice se dvěma prvky je *dvojice*
neboli *pár* (angl. *pair*); se třemi
prvky *trojice* (angl. *3-tuple*),
se čtyřmi *čtveřice* (angl. *4-tuple*), atd.
> [note]
-> Existují i n-tice s jedním prvkem (hmm… „jednice”?)
+> Pro úplnost: existují i n-tice s jedním prvkem (hmm… „jednice”?)
> a s nula prvky (prázdné n-tice, angl. *empty tuple*),
-> ale těmi se ze začátku nebudeme zabývat.
+> ale ty se v praxi tolik nepoužívají.
N-tice se tvoří jako seznamy, jen kolem sebe nemají hranaté závorky.
-Stačí čárky mezi prvky.
+Stačí čárky mezi prvky:
+
+```python
+dvojice = 'Pat', 'Mat'
+print(dvojice)
+```
Chovají se skoro stejně jako seznamy, jen nejdou měnit.
-Nemají tedy metody jako `append`
-a `pop` a nedá se jim přiřazovat do prvků.
-Dají se ale použít v cyklu `for`
-a dají se z nich číst jednotlivé prvky.
+Nemají tedy metody jako `append` a `pop` a nedá se jim přiřazovat do prvků
+(např. `ntice[1] = 2`).
+Dají se ale použít v cyklu `for` a dají se z nich číst jednotlivé prvky
+(např. `print(ntice[1])`).
```python
osoby = 'máma', 'teta', 'babička'
for osoba in osoby:
print(osoba)
-print('První je {}'.format(osoby[0]))
+
+prvni = osoby[0]
+print(f'První je {prvni}')
```
> [note]
> Vypadá to povědomě? Aby ne!
> N-tice jsme už použil{{gnd('i', 'y', both='i')}} dříve:
-> `for jmeno in 'Hynek', 'Vilém', 'Jarmila':`
-> ve skutečnosti používá n-tici!
+> `for pozdrav in 'Ahoj', 'Hello', 'Ciao':`
+> ve skutečnosti používá n-tici.
Když chceš n-tici předat do funkce,
narazíš na problém, že čárka odděluje jednotlivé
@@ -44,6 +50,10 @@ V podobných případech musíš n-tici
uzavřít do závorek, aby bylo jasné, že jde o jednu
hodnotu (byť složenou).
+```python
+print('osoby:', ('máma', 'teta', 'babička'))
+```
+
```python
seznam_dvojic = []
for i in range(10):
@@ -54,8 +64,8 @@ print(seznam_dvojic)
N-tice se hodí, pokud chceš z funkce vrátit
víc než jednu hodnotu.
-Prostě v příkazu `return` oddělíš vracené hodnoty čárkou.
-Vypadá to, že vracíš několik hodnot, ale
+Když u příkazu `return` použiješ několik hodnot oddělených čárkou,
+vypadá to, že vracíš několik hodnot, ale
ve skutečnosti se vrací jen jedna n-tice.
```python
@@ -64,69 +74,28 @@ def podil_a_zbytek(a, b):
```
> [note]
-> Tahle funkce už mimochodem v Pythonu je: jmenuje se
-> `divmod` a je vždy k dispozici
-> (nemusí se importovat).
+> Funkce „podíl a zbytek“ je mimochodem k dispozici přímo v Pythonu
+> pod jménem `divmod`.
-Python umí ještě jeden trik: pokud chceš přiřadit
-do několika proměnných najednou, stačí je na levé
+Python umí ještě jeden trik, takzvané „rozbalení“ (angl. *unpacking*).
+Když chceš přiřadit do několika proměnných najednou, stačí je na levé
straně rovnítka oddělit čárkou a na pravou stranu
-dát nějakou „složenou” hodnotu – třeba právě
-n-tici.
+dát nějakou „složenou” hodnotu – třeba právě n-tici.
```python
podil, zbytek = podil_a_zbytek(12, 5)
```
-N-tice se k tomuto účelu hodí nejvíc, ale
-jde to se všemi hodnotami, které jdou použít ve `for`:
-
-```python
-x, o = 'xo'
-jedna, dva, tri = [1, 2, 3]
-```
-
-## Funkce, které vracejí n-tice
-
-`zip` je zajímavá funkce.
-Používá se ve `for` cyklech, podobně jako funkce `range`, která „dává” čísla.
-
-Když funkce `zip` dostane dva seznamy
-(či jiné věci použitelné ve `for`),
-„dává” dvojice, a to tak, že nejdřív spáruje
-první prvek jednoho seznamu s prvním prvkem
-druhého seznamu,
-pak druhý s druhým, třetí s třetím a tak dál.
-
-Hodí se to, když máš dva seznamy se stejnou
-strukturou – příslušné prvky k sobě „patří”
-a chceš je zpracovávat společně:
-
-```python
-osoby = 'máma', 'teta', 'babička', 'vrah'
-vlastnosti = 'hodná', 'milá', 'laskavá', 'zákeřný'
-for osoba, vlastnost in zip(osoby, vlastnosti):
- print('{} je {}'.format(osoba, vlastnost))
-```
-
-Když `zip` dostane tři seznamy,
-bude tvořit trojice, ze čtyř seznamů nadělá čtveřice a tak dále.
-
-Další funkce, která vrací dvojice, je `enumerate`.
-Jako argument bere seznam (či jinou věc použitelnou
-ve `for`) a vždy spáruje index (pořadí v seznamu) s příslušným prvkem.
-Jako první tedy dá
-(0, *první prvek seznamu*), potom
-(1, *druhý prvek seznamu*),
-(2, *třetí prvek seznamu*)
-a tak dále.
-
-```python
-prvocisla = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29]
+> [note]
+> N-tice se k „rozbalování“ hodí nejvíc, protože mají
+> daný počet prvků.
+> Jde to ale použít se všemi hodnotami, které jdou použít ve `for`:
+>
+> ```python
+> ix, ocko = 'xo'
+> jedna, dva, tri = [1, 2, 3]
+> ```
-for i, prvocislo in enumerate(prvocisla):
- print('Prvočíslo č.{} je {}'.format(i, prvocislo))
-```
## Malé n-tice
@@ -155,25 +124,27 @@ nebo seznam karet v balíčku.
Oproti tomu `for pozdrav in 'Ahoj', 'Hello', 'Hola', 'Hei', 'SYN':`
používá n-tici.
+Když se počet prvků může v průběhu programu měnit, určitě sáhni po seznamu.
+Příklad budiž seznam přihlášených uživatelů, nevyřešených požadavků,
+karet v ruce nebo položek v inventáři.
+
N-tice se často používají na hodnoty
různých typů, kdy má každá „pozice”
v n-tici úplně jiný význam.
Například seznam můžeš použít na písmena abecedy,
-ale dvojice index–hodnota z `enumerate`
-je n-tice.
+ale dvojice „podíl a zbytek“ je n-tice.
Prázdné n-tice a n-tice s jedním
prvkem se zapisují trochu divně a má to své důvody:
může-li nastat situace, kdy takovou sekvenci budeš
potřebovat, většinou je lepší sáhnout po seznamu.
Například seznam hracích karet v ruce nebo
-seznam lidí aktuálně přihlášených do soutěže
-může být občas prázdný.
+seznam lidí aktuálně sledujících video může být občas prázdný.
Seznamy i n-tice mají i technické limity:
-n-tice nejdou měnit a až se naučíme pracovat se slovníky,
-zjistíme že seznamy tam nepůjdou použít jako klíče.
+n-tice nejdou měnit a až se naučíš pracovat se slovníky,
+zjistíš že seznamy tam nepůjdou použít jako klíče.
+V takových případech je potřeba použít ten druhý typ sekvence.
-Často není úplně jasné, který typ použít
-– v takovém případě je to pravděpodobně jedno.
-Řiď se instinktem. :)
+Často není úplně jasné, který typ použít.
+V takovém případě je to pravděpodobně jedno.
diff --git a/lessons/beginners/zip-enumerate/index.md b/lessons/beginners/zip-enumerate/index.md
new file mode 100644
index 0000000000..cd748d2227
--- /dev/null
+++ b/lessons/beginners/zip-enumerate/index.md
@@ -0,0 +1,259 @@
+# Iterátory n-tic
+
+Některé hodnoty v Pythonu jsou *iterovatelné* (angl. *iterable*):
+obsahují sekvenci jiných hodnot a lze je „projít“ (iterovat) cyklem `for` nebo
+je převést na seznam.
+Už jich známe několik:
+
+```pycon
+>>> list(range(10)) # sekvence čísel
+>>> list('ahoj') # řetězec
+>>> list(['Ahoj', 'Hello', 'Hei']) # seznam
+>>> list((12, 'Sr', True)) # n-tice
+```
+
+Spousta těchto typů umí něco navíc: zjistit jestli obsahují nějaký prvek
+(`4 in range(10)`), zjistit délku (`len([1, 2, 3])`), převést na velká písmena
+(`'abc'.upper()`).
+Nic z toho ale není potřeba, aby byl objekt iterovatelný.
+
+Podívejme se na dva další iterovatelné objekty: `enumerate` a `zip`.
+Oba jsou sekvence vytvořené z jiných, jednodušších sekvencí.
+
+
+## Enumerate: očíslování sekvence
+
+Funkce `enumerate` vezme nějakou existující sekvenci a *očísluje ji*:
+ve vrácené sekvenci budou dvojice (index, původní hodnota).
+
+Řekněme že máš tento seznam:
+
+```python
+trpaslici = ['Prófa', 'Stydlín', 'Dřímal', 'Kejchal', 'Štístko',
+ 'Šmudla', 'Rejpal']
+```
+
+Když na něj použiješ `enumerate`, dostaneš objekt `enumerate`,
+který podobně jako `range()` neukáže svůj obsah rovnou,
+ale můžeš se „do něj podívat“ převedením na seznam.
+Uvidíš tak seznam dvojic (číslo, trpaslík):
+
+```pycon
+>>> enumerate(trpaslici)
+
+>>> list(enumerate(trpaslici))
+[(0, 'Prófa'), (1, 'Stydlín'), (2, 'Dřímal'), (3, 'Kejchal'), (4, 'Štístko'), (5, 'Šmudla'), (6, 'Rejpal')]
+```
+
+Místo převedení na seznam můžeš přes objekt `enumerate` iterovat cyklem `for`
+a pro každou dvojici něco udělat.
+Třeba ji hezky vypsat:
+
+```python
+for dvojice in enumerate(trpaslici):
+ # Rozbalení dvojice
+ index, trpaslik = dvojice
+ # Vypsání
+ print(f'Na pozici {index} je {trpaslik}!')
+```
+
+Objekt, který funkce `enumerate` vrací, je *iterátor dvojic* – sekvence,
+jejíž prvky jsou dvojice.
+
+Sekvence `enumerate` toho „umí“ ještě míň než seznam nebo `range`.
+Nejde z ní ani vybírat prvky, o metodách jako `append` ani nemluvě:
+
+```pycon
+>>> enumerate(trpaslici)[3]
+Traceback (most recent call last):
+ File "", line 1, in
+TypeError: 'enumerate' object is not subscriptable
+```
+
+Když budeš od sekvence `enumerate` chtít něco víc než iterování,
+převeď ji na seznam.
+
+
+## Rozbalování v cyklu for
+
+Cyklus `for` umíš rozepsat: opakuje se v něm nastavení proměnné (které dělá
+`for` za tebe), pak tělo cyklu, a znovu nastavení proměnné, tělo cyklu atd.
+Pro „trpasličí“ cyklus to je:
+
+```python
+dvojice = 0, 'Prófa' # nastavení proměnné dělá `for`
+index, trpaslik = dvojice
+print(f'Na pozici {index} je {trpaslik}!')
+
+dvojice = 1, 'Stydlín' # nastavení proměnné dělá `for`
+index, trpaslik = dvojice
+print(f'Na pozici {index} je {trpaslik}!')
+
+dvojice = 2, 'Dřímal' # nastavení proměnné dělá `for`
+index, trpaslik = dvojice
+print(f'Na pozici {index} je {trpaslik}!')
+
+# A tak dále
+```
+
+Kdybys to psal{{a}} ručně, lze to zjednodušit – přiřadit do dvou proměnných
+najednou, bez pomocné proměnné `dvojice`:
+
+```python
+index, trpaslik = 0, 'Prófa' # nastavení proměnných
+print(f'Na pozici {index} je {trpaslik}!')
+
+index, trpaslik = 1, 'Stydlín' # nastavení proměnných
+print(f'Na pozici {index} je {trpaslik}!')
+
+index, trpaslik = 2, 'Dřímal' # nastavení proměnných
+print(f'Na pozici {index} je {trpaslik}!')
+
+# A tak dále
+```
+
+Cyklus `for` tohle ve skutečnosti umí: místo do proměnné `dvojice` může
+přiřadit rovnou do dvou proměnných `index, trpaslik`:
+
+```python
+for index, trpaslik in enumerate(trpaslici):
+ print(f'Na pozici {index} je {trpaslik}!')
+```
+
+Tohle je docela častý způsob práce s *iterátorem n-tic* – máš-li sekvenci,
+jejíž prvky jsou n-tice, můžeš jednotlivé součásti n-tice
+rozbalit přímo v hlavičce `for` cyklu.
+
+Zkus si to! Zkopíruj si tento seznam:
+
+```python
+dny = ['Po', 'Út', 'St', 'Čt', 'Pá', 'So', 'Ne']
+```
+
+… a zkus vypsat:
+
+```plain
+1. Po
+2. Út
+3. St
+4. Čt
+5. Pá
+6. So
+7. Ne
+```
+
+{% filter solution %}
+
+```python
+dny = ['Po', 'Út', 'St', 'Čt', 'Pá', 'So', 'Ne']
+for index, den in enumerate(dny):
+ cislo = index + 1
+ print(f'{cislo}. {den}')
+```
+
+To je trošku kostrbaté, ale dá se to zjednodušit: buď jako
+`f'{cislo + 1}. {den}'`, nebo můžeš funkci `enumerate` předat
+pojmenovaný argument `start`, pomocí kterého umí sama
+počítat od jiného začátku než od nuly:
+
+```python
+dny = ['Po', 'Út', 'St', 'Čt', 'Pá', 'So', 'Ne']
+for index, den in enumerate(dny, start=1):
+ print(f'{index}. {den}')
+```
+
+{% endfilter %}
+
+
+## Zip: Víc iterací najednou
+
+Další iterátor n-tic je funkce `zip`, která umí projít dvě sekvence
+naráz.
+
+Řekněme že máš seznam věcí a druhý seznam, ve kterém jsou barvy těch věcí:
+
+``` python
+veci = ['tráva', 'slunce', 'mrkev', 'list']
+barvy = ['zelená', 'žluté', 'oranžová', 'zelený']
+```
+
+Když na ně zavoláš `zip`, dostaneš iterátor, který (podobně jako `enumerate`
+nebo `range`) sám od sebe nic neříká:
+
+```pycon
+>>> zip(veci, barvy)
+
+```
+
+Po převedení na seznam se ale ukáže seznam odpovídajících si dvojic:
+
+* Dvojice prvních prvků obou seznamů: (`tráva`, `zelená`)
+* Dvojice druhých prvků obou seznamů: (`slunce`, `žluté`)
+* Dvojice třetích prvků obou seznamů: (`mrkev`, `oranžová`)
+* A tak dál…
+
+```pycon
+>>> list(zip(veci, barvy))
+[('tráva', 'zelená'), ('slunce', 'žluté'), ('mrkev', 'oranžová'), ('list', 'zelený')]
+```
+
+Takové dvojice jsou připravené na to, že je rozbalíš v cyklu `for`:
+
+``` python
+for vec, barva in zip(veci, barvy):
+ print(f"{vec} je {barva}")
+```
+
+Funguje to i pro více sekvencí.
+V následujícím případě vznikne iterátor čtveřic (věc, barva,
+místo, číslo):
+
+```python
+veci = ['tráva', 'slunce', 'mrkev', 'list']
+barvy = ['zelená', 'žluté', 'oranžová', 'zelený']
+mista = ['na zemi', 'nahoře', 'na talíři', 'na stromě']
+cisla = range(4)
+
+for vec, barva, misto, cislo in zip(veci, barvy, mista, cisla):
+ print(f"{cislo}. {barva} {vec} je {misto}")
+```
+
+
+## Zip Longest: Pro ty co chtějí všechno
+
+Jak se `zip` chová, když dostane seznamy různých délek?
+
+```python
+veci = ['tráva', 'slunce', 'mrkev', 'list', 'myšlenka', 'spravedlnost']
+barvy = ['zelená', 'žluté', 'oranžová', 'zelený']
+for vec, barva in zip(veci, barvy):
+ print(f"{vec} je {barva}")
+```
+
+{% filter solution %}
+Iterátor `zip` skončí hned když dojdou prvky nejkratší sekvence.
+{% endfilter %}
+
+Občas je potřeba projít všechny záznamy.
+Na to slouží funkce `zip_longest` z modulu `itertools`:
+
+```python
+from itertools import zip_longest
+for vec, barva in zip_longest(veci, barvy, fillvalue='(nevím)'):
+ print(f"{vec} je {barva}")
+```
+
+Pojmenovaný argument `fillvalue` říká, co se doplní za chybějící hodnoty.
+Když ho nezadáš, doplní se `None` („nic“, hodnota kterou např. vrací procedury).
+To se často používá, když je pro chybějící hodnoty potřeba nějaká
+složitější logika:
+
+```python
+from itertools import zip_longest
+for vec, barva in zip_longest(veci, barvy):
+ if vec == None:
+ vec = 'nějaká věc'
+ if barva == None:
+ barva = 'bez barvy'
+ print(f"{vec} je {barva}")
+```
diff --git a/lessons/beginners/zip-enumerate/info.yml b/lessons/beginners/zip-enumerate/info.yml
new file mode 100644
index 0000000000..566e2e99ed
--- /dev/null
+++ b/lessons/beginners/zip-enumerate/info.yml
@@ -0,0 +1,4 @@
+title: Iterátory n-tic
+style: md
+attribution: Pro PyLadies Brno napsal Petr Viktorin, 2014-2019.
+license: cc-by-sa-40