-
Notifications
You must be signed in to change notification settings - Fork 119
Rework lessons on strings #628
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
7 commits
Select commit
Hold shift + click to select a range
121daed
Reword and split str lesson
encukou 14354c1
str-index-slice: Fix examples & align with diagram
encukou c4b7a0b
Rewordings for the `str` session
encukou 72cd435
Add heading for stub on all the string methods
encukou d1b84c3
More string rewordings
encukou d4dadac
beginners/str: Fix typos
encukou 29351bd
Add some continuity to note about strinbg immutability
encukou File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,188 @@ | ||
| # Výběr z řetězců | ||
|
|
||
|
|
||
| Už umíš spojovat dohromady kratší řetězce: | ||
|
|
||
| ```python | ||
| spojeny_retezec = 'a' + 'b' | ||
| dlouhy_retezec = 'ó' * 100 | ||
| ``` | ||
| Teď se podíváme na opačný proces: jak z dlouhého | ||
| řetězce dostat kratší součásti. | ||
| Začneme jednotlivými znaky. | ||
|
|
||
|
|
||
| ## Výběr znaku | ||
|
|
||
| Konkrétní znak na dané pozici se z řetězce dá vybrat operací *vybrání prvku* | ||
| (angl. *subscripting*), | ||
| která se píše podobně jako volání funkce, jen s hranatými závorkami. | ||
| Třeba takhle se dá vybrat znak na páté pozici: | ||
|
|
||
| ```python | ||
| pate_pismeno = 'čokoláda'[5] | ||
|
|
||
| print(pate_pismeno) | ||
| ``` | ||
|
|
||
| Funguje to? Dostal{{a}} jsi opravdu páté písmeno? | ||
|
|
||
| {% filter solution %} | ||
| Nedostal{{a}} – dostal{{a}} jsi *šesté* písmeno. | ||
| {% endfilter %} | ||
|
|
||
| Jak sis možná už všiml{{a}}, programátoři počítají od nuly. | ||
| „První“ prvek má vždy číslo nula, druhý číslo jedna a tak dál. | ||
|
|
||
| Stejně je to i se znaky v řetězcích. První písmeno má číslo nula, | ||
| druhé jedna, ... a osmé písmeno má číslo sedm. | ||
|
|
||
| Proč je tomu tak? | ||
| K úplnému pochopení důvodů by ses potřeboval{{a}} | ||
| naučit něco o ukazatelích a polích, | ||
| což nebude hned, takže pro teď nám bude | ||
| stačit vědět, | ||
| že programátoři jsou prostě divní. | ||
|
|
||
| Nebo aspoň že mají rádi divná čísla – jako nulu. | ||
|
|
||
| ```plain | ||
| [0] [1] [2] [3] [4] [5] [6] [7] | ||
|
|
||
| ╭───┬───┬───┬───┬───┬───┬───┬───╮ | ||
| │ Č │ o │ k │ o │ l │ á │ d │ a │ | ||
| ╰───┴───┴───┴───┴───┴───┴───┴───╯ | ||
| ``` | ||
|
|
||
|
|
||
| A když už jsme u divných čísel, | ||
| co se asi stane, když budu vybírat písmena pomocí záporných čísel? | ||
|
|
||
| {% filter solution %} | ||
| ```python | ||
| print('Čokoláda'[-1]) # → a | ||
| print('Čokoláda'[-2]) # → d | ||
| print('Čokoláda'[-3]) # → á | ||
| print('Čokoláda'[-4]) # → l | ||
| ``` | ||
|
|
||
| Záporná čísla vybírají písmenka od konce. | ||
|
|
||
| ```plain | ||
| [0] [1] [2] [3] [4] [5] [6] [7] | ||
| [-8][-7][-6][-5][-4][-3][-2][-1] | ||
| ╭───┬───┬───┬───┬───┬───┬───┬───╮ | ||
| │ Č │ o │ k │ o │ l │ á │ d │ a │ | ||
| ╰───┴───┴───┴───┴───┴───┴───┴───╯ | ||
| ``` | ||
| {% endfilter %} | ||
|
|
||
|
|
||
|
|
||
| ## Sekání řetězců | ||
|
|
||
| Kromě jednotlivých znaků můžeme vybírat i delší části – odborně | ||
| *podřetězce* (angl. *substrings*). | ||
|
|
||
| Zkus, co dělá tenhle program: | ||
|
|
||
| ```python | ||
| retezec = 'čokoláda' | ||
| kousek = retezec[5:] | ||
| print(kousek) | ||
| ``` | ||
|
|
||
| {% filter solution %} | ||
| Zápis `retezec[5:]` vybere *podřetězec* od znaku číslo 5 dál. | ||
| {% endfilter %} | ||
|
|
||
| Dá se použít i `retezec[:5]`, | ||
| který vybere všechno *až po* znak číslo 5. | ||
| Ne však znak 5 samotný, což je možná trochu zarážející, | ||
| ale je potřeba s tím počítat. | ||
| Poslední prvek není ve výběru obsažen, podobně jako `range(5)` neobsahuje | ||
| číslo 5. | ||
|
|
||
| Ačkoli je tohle chování divné, má hezké důsledky. | ||
| Všimni si třeba, že `retezec[:5] + retezec[5:]` ti dá zpět původní `retezec`. | ||
|
|
||
| Podobnému vybírání podřetězců se říká „sekání“ řetězců | ||
| (angl. *string slicing*). | ||
|
|
||
| Sekání „od“ a „do“ se dá kombinovat. | ||
| Zkus si to: co asi udělají následující příkazy? | ||
|
|
||
| ```python | ||
| retezec = 'čokoláda' | ||
| print(retezec[:4]) | ||
| print(retezec[2:6]) | ||
| print(retezec[-3:]) | ||
| print(retezec[:]) | ||
| ``` | ||
|
|
||
| {% filter solution %} | ||
| Zápis `retezec[od:do]` vybere *podřetězec* od pozice `od` do pozice `do`. | ||
| Když jednu z hodnot vynecháš, vybírá se od začádku, resp. do konce. | ||
|
|
||
| ```python | ||
| retezec = 'čokoláda' | ||
| print(retezec[:4]) # → čoko | ||
| print(retezec[2:6]) # → kolá | ||
| print(retezec[-3:]) # → áda | ||
| print(retezec[:]) # → čokoláda | ||
| ``` | ||
| {% endfilter %} | ||
|
|
||
| Určování vhodných čísel, *indexů*, občas vyžaduje trochu zamyšlení. | ||
|
|
||
| U sekání (s `:`) pomáhá očíslovat si „hranice“ mezi znaky, | ||
| abys v tom měl{{a}} lepší přehled: | ||
|
|
||
| {{ anchor('slicing-diagram') }} | ||
| ```plain | ||
| ╭───┬───┬───┬───┬───┬───┬───┬───╮ | ||
| │ Č │ o │ k │ o │ l │ á │ d │ a │ | ||
| ├───┼───┼───┼───┼───┼───┼───┼───┤ | ||
| │ │ │ │ │ │ │ │ │ | ||
| 0 1 2 3 4 5 6 7 8 | ||
| -8 -7 -6 -5 -4 -3 -2 -1 | ||
|
|
||
| ╰───────────────╯ | ||
| 'čokoláda'[:4] == 'čoko' | ||
|
|
||
| ╰───────────────╯ | ||
| 'čokoláda'[2:6] == 'kolá' | ||
|
|
||
| ╰───────────╯ | ||
| 'čokoláda'[-3:] == 'áda' | ||
| ``` | ||
|
|
||
|
|
||
| ## Cvičení | ||
|
|
||
| Zkus napsat funkci `zamen(retezec, pozice, znak)`. | ||
|
|
||
| Tato funkce vrátí řetězec, který má na dané pozici | ||
| daný znak; jinak je stejný jako původní `retezec`. Například: | ||
|
|
||
| ```python | ||
| # Zaměň třetí znak ve slově "čokoláda" | ||
| print(zamen('čokoláda', 3, 'u')) # → čokuláda | ||
| ``` | ||
|
|
||
| Pozor na to, že řetězce v Pythonu nelze měnit. | ||
| Nemůžeš v existujícím řetězci zaměnit jeden znak za jiný; | ||
| musíš vytvořit nový řetězec poskládaný z částí toho starého. | ||
|
|
||
| {% filter solution %} | ||
| ```python | ||
| def zamen(retezec, pozice, znak): | ||
| """Zamění znak na dané pozici | ||
|
|
||
| Vrátí řetězec, který má na dané pozici daný znak; | ||
| jinak je stejný jako vstupní retezec | ||
| """ | ||
|
|
||
| return retezec[:pozice] + znak + retezec[pozice + 1:] | ||
| ``` | ||
| {% endfilter %} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| title: Výběr z řetězců | ||
| style: md | ||
| attribution: | ||
| - Pro PyLadies Brno napsal Petr Viktorin, 2014-2019. | ||
| license: cc-by-sa-40 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,110 @@ | ||
| # Řetězcové funkce a metody | ||
|
|
||
| Řetězce umí všelijaké triky. | ||
| Funkcí `len()` můžeš zjistit, jak je řetězec dlouhý; | ||
| operátorem `in` pak jestli v sobě obsahuje daný podřetězec. | ||
|
|
||
| <table class="table"> | ||
| <tr> | ||
| <th>Zápis</th> | ||
| <th>Popis</th> | ||
| <th>Příklad</th> | ||
| </tr> | ||
| <tr> | ||
| <td><code>len(r)</code></td> | ||
| <td>Délka řetězce</td> | ||
| <td><code>len('čokoláda')</code></td> | ||
| </tr> | ||
| <tr> | ||
| <td><code>x in r</code></td> | ||
| <td>True pokud je řetězec <code>x</code> obsažen v <code>r</code></td> | ||
| <td><code>'oko' in 'čokoláda'</code></td> | ||
| </tr> | ||
| <tr> | ||
| <td><code>x not in r</code></td> | ||
| <td>Opak <code>x in r</code></td> | ||
| <td><code>'dub' not in 'čokoláda</code></td> | ||
| </tr> | ||
| </table> | ||
|
|
||
| Řetězce vždy berou v potaz velikost písmen, | ||
| takže např. `'ČOKO' in 'čokoláda'` je `False`. | ||
| Kdybys chtěl{{a}} porovnávat bez ohledu na velikost písmen, | ||
| musel{{a}} bys oba řetězce převést třeba na malá písmena | ||
| a pak je porovnat. | ||
|
|
||
| A jak se převádí na malá písmena? | ||
| K tomu budeme potřebovat další novou vlastnost Pythonu: metody. | ||
|
|
||
| ## Metody | ||
|
|
||
| *Metoda* (angl. *method*) je jako funkce – něco, co se dá zavolat. | ||
| Na rozdíl od funkce je svázaná s nějakým *objektem* (hodnotou). | ||
| Volá se tak, že se za objekt napíše tečka, | ||
| za ní jméno metody a za to celé se, jako u funkcí, připojí závorky | ||
| s případnými argumenty. | ||
|
|
||
| Řetězcové metody `upper()` a `lower()` | ||
| převádí text na velká, respektive malá písmena. | ||
| Zkus si to! | ||
|
|
||
| ```python | ||
| retezec = 'Ahoj' | ||
| print(retezec.upper()) | ||
| print(retezec.lower()) | ||
| print(retezec) | ||
| ``` | ||
|
|
||
| > [note] | ||
| > Všimni si, že původní řetězec se nemění; metoda vrátí nový řetězec, ten | ||
| > starý zůstává. | ||
| > | ||
| > To je obecná vlastnost řetězců v Pythonu: jednou existující řetězec se už | ||
| > nedá změnit, dá se jen vytvořit nějaký odvozený. | ||
| > S touto vlastností už ses mohl{{a}} setkat při psaní funkce `zamen`. | ||
|
|
||
|
|
||
| ### Iniciály | ||
|
|
||
| Pro procvičení metod a vybírání znaků si zkus napsat program, | ||
| který se zeptá na jméno, pak na příjmení | ||
| a pak vypíše iniciály – první písmena zadaných jmen. | ||
|
|
||
| Iniciály jsou vždycky velkými písmeny | ||
| (i kdyby byl uživatel líný mačkat Shift). | ||
|
|
||
| {% filter solution %} | ||
| ```python | ||
| jmeno = input('Zadej jméno: ') | ||
| prijmeni = input('Zadej příjmení ') | ||
| inicialy = jmeno[0] + prijmeni[0] | ||
| print('Iniciály:', inicialy.upper()) | ||
| ``` | ||
|
|
||
| Způsobů, jak takový program napsat, je více. | ||
| Lze například zavolat `upper()` dvakrát – zvlášť na jméno a zvlášť na příjmení. | ||
|
|
||
| Nebo to jde zapsat i takto – | ||
| metoda se dá volat na výsledku jakéhokoli výrazu: | ||
|
|
||
| ```python | ||
| jmeno = input('Zadej jméno: ') | ||
| prijmeni = input('Zadej příjmení ') | ||
| print('Iniciály:', (jmeno[0] + prijmeni[0]).upper()) | ||
| ``` | ||
|
|
||
| Doporučuji spíš první způsob, ten se smysluplnými názvy proměnných. | ||
| Je sice delší, ale mnohem přehlednější. | ||
| {% endfilter %} | ||
|
|
||
|
|
||
| ### A další | ||
|
|
||
| Řetězcových metod je celá řada. | ||
| 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. | ||
| Podívej se na ně a zjisti, co dělají. | ||
|
|
||
| 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áš). | ||
|
|
||
| Všimni si, že `len` není metoda, ale funkce; píše se `len(r)`, ne `r.len()`. | ||
| Proč tomu tak je, to za nějakou dobu poznáš. | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| title: Řetězcové funkce a metody | ||
| style: md | ||
| attribution: | ||
| - Pro PyLadies Brno napsal Petr Viktorin, 2014-2019. | ||
| license: cc-by-sa-40 |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.