Skip to content

Commit f8de71a

Browse files
authored
Rework lessons on strings
In in-person courses, I tended to explain strings in more depth than what the materials provided. There's enough depth in quoting and characters (esp. special characters) to make it a separate lesson; same goes for the new concepts of indexing/slicing and methods. This splits the material into: String literals (how to write strings; what is a character) String indexing and slicing String methods F-strings (split out earlier) pyvec#628
2 parents 39a1136 + 29351bd commit f8de71a

8 files changed

Lines changed: 1006 additions & 266 deletions

File tree

courses/pyladies/info.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,8 @@ plan:
6060
materials:
6161
- lesson: beginners/def
6262
- lesson: beginners/str
63+
- lesson: beginners/str-index-slice
64+
- lesson: beginners/str-methods
6365
- lesson: beginners/fstring
6466
- title: Řetězcový tahák
6567
url: https://pyvec.github.io/cheatsheets/strings/strings-cs.pdf
Lines changed: 188 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,188 @@
1+
# Výběr z řetězců
2+
3+
4+
Už umíš spojovat dohromady kratší řetězce:
5+
6+
```python
7+
spojeny_retezec = 'a' + 'b'
8+
dlouhy_retezec = 'ó' * 100
9+
```
10+
Teď se podíváme na opačný proces: jak z dlouhého
11+
řetězce dostat kratší součásti.
12+
Začneme jednotlivými znaky.
13+
14+
15+
## Výběr znaku
16+
17+
Konkrétní znak na dané pozici se z řetězce dá vybrat operací *vybrání prvku*
18+
(angl. *subscripting*),
19+
která se píše podobně jako volání funkce, jen s hranatými závorkami.
20+
Třeba takhle se dá vybrat znak na páté pozici:
21+
22+
```python
23+
pate_pismeno = 'čokoláda'[5]
24+
25+
print(pate_pismeno)
26+
```
27+
28+
Funguje to? Dostal{{a}} jsi opravdu páté písmeno?
29+
30+
{% filter solution %}
31+
Nedostal{{a}} – dostal{{a}} jsi *šesté* písmeno.
32+
{% endfilter %}
33+
34+
Jak sis možná už všiml{{a}}, programátoři počítají od nuly.
35+
„První“ prvek má vždy číslo nula, druhý číslo jedna a tak dál.
36+
37+
Stejně je to i se znaky v řetězcích. První písmeno má číslo nula,
38+
druhé jedna, ... a osmé písmeno má číslo sedm.
39+
40+
Proč je tomu tak?
41+
K úplnému pochopení důvodů by ses potřeboval{{a}}
42+
naučit něco o ukazatelích a polích,
43+
což nebude hned, takže pro teď nám bude
44+
stačit vědět,
45+
že programátoři jsou prostě divní.
46+
47+
Nebo aspoň že mají rádi divná čísla – jako nulu.
48+
49+
```plain
50+
[0] [1] [2] [3] [4] [5] [6] [7]
51+
52+
╭───┬───┬───┬───┬───┬───┬───┬───╮
53+
│ Č │ o │ k │ o │ l │ á │ d │ a │
54+
╰───┴───┴───┴───┴───┴───┴───┴───╯
55+
```
56+
57+
58+
A když už jsme u divných čísel,
59+
co se asi stane, když budu vybírat písmena pomocí záporných čísel?
60+
61+
{% filter solution %}
62+
```python
63+
print('Čokoláda'[-1]) # → a
64+
print('Čokoláda'[-2]) # → d
65+
print('Čokoláda'[-3]) # → á
66+
print('Čokoláda'[-4]) # → l
67+
```
68+
69+
Záporná čísla vybírají písmenka od konce.
70+
71+
```plain
72+
[0] [1] [2] [3] [4] [5] [6] [7]
73+
[-8][-7][-6][-5][-4][-3][-2][-1]
74+
╭───┬───┬───┬───┬───┬───┬───┬───╮
75+
│ Č │ o │ k │ o │ l │ á │ d │ a │
76+
╰───┴───┴───┴───┴───┴───┴───┴───╯
77+
```
78+
{% endfilter %}
79+
80+
81+
82+
## Sekání řetězců
83+
84+
Kromě jednotlivých znaků můžeme vybírat i delší části – odborně
85+
*podřetězce* (angl. *substrings*).
86+
87+
Zkus, co dělá tenhle program:
88+
89+
```python
90+
retezec = 'čokoláda'
91+
kousek = retezec[5:]
92+
print(kousek)
93+
```
94+
95+
{% filter solution %}
96+
Zápis `retezec[5:]` vybere *podřetězec* od znaku číslo 5 dál.
97+
{% endfilter %}
98+
99+
Dá se použít i `retezec[:5]`,
100+
který vybere všechno *až po* znak číslo 5.
101+
Ne však znak 5 samotný, což je možná trochu zarážející,
102+
ale je potřeba s tím počítat.
103+
Poslední prvek není ve výběru obsažen, podobně jako `range(5)` neobsahuje
104+
číslo 5.
105+
106+
Ačkoli je tohle chování divné, má hezké důsledky.
107+
Všimni si třeba, že `retezec[:5] + retezec[5:]` ti dá zpět původní `retezec`.
108+
109+
Podobnému vybírání podřetězců se říká „sekání“ řetězců
110+
(angl. *string slicing*).
111+
112+
Sekání „od“ a „do“ se dá kombinovat.
113+
Zkus si to: co asi udělají následující příkazy?
114+
115+
```python
116+
retezec = 'čokoláda'
117+
print(retezec[:4])
118+
print(retezec[2:6])
119+
print(retezec[-3:])
120+
print(retezec[:])
121+
```
122+
123+
{% filter solution %}
124+
Zápis `retezec[od:do]` vybere *podřetězec* od pozice `od` do pozice `do`.
125+
Když jednu z hodnot vynecháš, vybírá se od začádku, resp. do konce.
126+
127+
```python
128+
retezec = 'čokoláda'
129+
print(retezec[:4]) # → čoko
130+
print(retezec[2:6]) # → kolá
131+
print(retezec[-3:]) # → áda
132+
print(retezec[:]) # → čokoláda
133+
```
134+
{% endfilter %}
135+
136+
Určování vhodných čísel, *indexů*, občas vyžaduje trochu zamyšlení.
137+
138+
U sekání (s `:`) pomáhá očíslovat si „hranice“ mezi znaky,
139+
abys v tom měl{{a}} lepší přehled:
140+
141+
{{ anchor('slicing-diagram') }}
142+
```plain
143+
╭───┬───┬───┬───┬───┬───┬───┬───╮
144+
│ Č │ o │ k │ o │ l │ á │ d │ a │
145+
├───┼───┼───┼───┼───┼───┼───┼───┤
146+
│ │ │ │ │ │ │ │ │
147+
0 1 2 3 4 5 6 7 8
148+
-8 -7 -6 -5 -4 -3 -2 -1
149+
150+
╰───────────────╯
151+
'čokoláda'[:4] == 'čoko'
152+
153+
╰───────────────╯
154+
'čokoláda'[2:6] == 'kolá'
155+
156+
╰───────────╯
157+
'čokoláda'[-3:] == 'áda'
158+
```
159+
160+
161+
## Cvičení
162+
163+
Zkus napsat funkci `zamen(retezec, pozice, znak)`.
164+
165+
Tato funkce vrátí řetězec, který má na dané pozici
166+
daný znak; jinak je stejný jako původní `retezec`. Například:
167+
168+
```python
169+
# Zaměň třetí znak ve slově "čokoláda"
170+
print(zamen('čokoláda', 3, 'u')) # → čokuláda
171+
```
172+
173+
Pozor na to, že řetězce v Pythonu nelze měnit.
174+
Nemůžeš v existujícím řetězci zaměnit jeden znak za jiný;
175+
musíš vytvořit nový řetězec poskládaný z částí toho starého.
176+
177+
{% filter solution %}
178+
```python
179+
def zamen(retezec, pozice, znak):
180+
"""Zamění znak na dané pozici
181+
182+
Vrátí řetězec, který má na dané pozici daný znak;
183+
jinak je stejný jako vstupní retezec
184+
"""
185+
186+
return retezec[:pozice] + znak + retezec[pozice + 1:]
187+
```
188+
{% endfilter %}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
title: Výběr z řetězců
2+
style: md
3+
attribution:
4+
- Pro PyLadies Brno napsal Petr Viktorin, 2014-2019.
5+
license: cc-by-sa-40
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
# Řetězcové funkce a metody
2+
3+
Řetězce umí všelijaké triky.
4+
Funkcí `len()` můžeš zjistit, jak je řetězec dlouhý;
5+
operátorem `in` pak jestli v sobě obsahuje daný podřetězec.
6+
7+
<table class="table">
8+
<tr>
9+
<th>Zápis</th>
10+
<th>Popis</th>
11+
<th>Příklad</th>
12+
</tr>
13+
<tr>
14+
<td><code>len(r)</code></td>
15+
<td>Délka řetězce</td>
16+
<td><code>len('čokoláda')</code></td>
17+
</tr>
18+
<tr>
19+
<td><code>x&nbsp;in&nbsp;r</code></td>
20+
<td>True pokud je řetězec <code>x</code> obsažen v <code>r</code></td>
21+
<td><code>'oko' in 'čokoláda'</code></td>
22+
</tr>
23+
<tr>
24+
<td><code>x&nbsp;not&nbsp;in&nbsp;r</code></td>
25+
<td>Opak <code>x in r</code></td>
26+
<td><code>'dub' not in 'čokoláda</code></td>
27+
</tr>
28+
</table>
29+
30+
Řetězce vždy berou v potaz velikost písmen,
31+
takže např. `'ČOKO' in 'čokoláda'` je `False`.
32+
Kdybys chtěl{{a}} porovnávat bez ohledu na velikost písmen,
33+
musel{{a}} bys oba řetězce převést třeba na malá písmena
34+
a pak je porovnat.
35+
36+
A jak se převádí na malá písmena?
37+
K tomu budeme potřebovat další novou vlastnost Pythonu: metody.
38+
39+
## Metody
40+
41+
*Metoda* (angl. *method*) je jako funkce – něco, co se dá zavolat.
42+
Na rozdíl od funkce je svázaná s nějakým *objektem* (hodnotou).
43+
Volá se tak, že se za objekt napíše tečka,
44+
za ní jméno metody a za to celé se, jako u funkcí, připojí závorky
45+
s případnými argumenty.
46+
47+
Řetězcové metody `upper()` a `lower()`
48+
převádí text na velká, respektive malá písmena.
49+
Zkus si to!
50+
51+
```python
52+
retezec = 'Ahoj'
53+
print(retezec.upper())
54+
print(retezec.lower())
55+
print(retezec)
56+
```
57+
58+
> [note]
59+
> Všimni si, že původní řetězec se nemění; metoda vrátí nový řetězec, ten
60+
> starý zůstává.
61+
>
62+
> To je obecná vlastnost řetězců v Pythonu: jednou existující řetězec se už
63+
> nedá změnit, dá se jen vytvořit nějaký odvozený.
64+
> S touto vlastností už ses mohl{{a}} setkat při psaní funkce `zamen`.
65+
66+
67+
### Iniciály
68+
69+
Pro procvičení metod a vybírání znaků si zkus napsat program,
70+
který se zeptá na jméno, pak na příjmení
71+
a pak vypíše iniciály – první písmena zadaných jmen.
72+
73+
Iniciály jsou vždycky velkými písmeny
74+
(i kdyby byl uživatel líný mačkat Shift).
75+
76+
{% filter solution %}
77+
```python
78+
jmeno = input('Zadej jméno: ')
79+
prijmeni = input('Zadej příjmení ')
80+
inicialy = jmeno[0] + prijmeni[0]
81+
print('Iniciály:', inicialy.upper())
82+
```
83+
84+
Způsobů, jak takový program napsat, je více.
85+
Lze například zavolat `upper()` dvakrát – zvlášť na jméno a zvlášť na příjmení.
86+
87+
Nebo to jde zapsat i takto –
88+
metoda se dá volat na výsledku jakéhokoli výrazu:
89+
90+
```python
91+
jmeno = input('Zadej jméno: ')
92+
prijmeni = input('Zadej příjmení ')
93+
print('Iniciály:', (jmeno[0] + prijmeni[0]).upper())
94+
```
95+
96+
Doporučuji spíš první způsob, ten se smysluplnými názvy proměnných.
97+
Je sice delší, ale mnohem přehlednější.
98+
{% endfilter %}
99+
100+
101+
### A další
102+
103+
Řetězcových metod je celá řada.
104+
Nejužitečnější z nich najdeš v [taháku](https://pyvec.github.io/cheatsheets/strings/strings-cs.pdf), který si můžeš stáhnout či vytisknout.
105+
Podívej se na ně a zjisti, co dělají.
106+
107+
A úplně všechny řetězcové metody jsou popsány v [dokumentaci Pythonu](https://docs.python.org/3/library/stdtypes.html#string-methods) (anglicky; plné věcí, které ještě neznáš).
108+
109+
Všimni si, že `len` není metoda, ale funkce; píše se `len(r)`, ne `r.len()`.
110+
Proč tomu tak je, to za nějakou dobu poznáš.
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
title: Řetězcové funkce a metody
2+
style: md
3+
attribution:
4+
- Pro PyLadies Brno napsal Petr Viktorin, 2014-2019.
5+
license: cc-by-sa-40

0 commit comments

Comments
 (0)