diff --git a/courses/pyladies/info.yml b/courses/pyladies/info.yml index 0fc8ade02c..9795a24fd5 100644 --- a/courses/pyladies/info.yml +++ b/courses/pyladies/info.yml @@ -60,6 +60,8 @@ plan: materials: - lesson: beginners/def - lesson: beginners/str + - lesson: beginners/str-index-slice + - lesson: beginners/str-methods - lesson: beginners/fstring - title: Řetězcový tahák url: https://pyvec.github.io/cheatsheets/strings/strings-cs.pdf diff --git a/lessons/beginners/str-index-slice/index.md b/lessons/beginners/str-index-slice/index.md new file mode 100644 index 0000000000..fc5385e57a --- /dev/null +++ b/lessons/beginners/str-index-slice/index.md @@ -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 %} diff --git a/lessons/beginners/str-index-slice/info.yml b/lessons/beginners/str-index-slice/info.yml new file mode 100644 index 0000000000..47fe797592 --- /dev/null +++ b/lessons/beginners/str-index-slice/info.yml @@ -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 diff --git a/lessons/beginners/str-methods/index.md b/lessons/beginners/str-methods/index.md new file mode 100644 index 0000000000..b96ad17dbb --- /dev/null +++ b/lessons/beginners/str-methods/index.md @@ -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. + + + + + + + + + + + + + + + + + + + + + + +
ZápisPopisPříklad
len(r)Délka řetězcelen('čokoláda')
x in rTrue pokud je řetězec x obsažen v r'oko' in 'čokoláda'
x not in rOpak x in r'dub' not in 'čokoláda
+ +Ř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áš. diff --git a/lessons/beginners/str-methods/info.yml b/lessons/beginners/str-methods/info.yml new file mode 100644 index 0000000000..f16a441915 --- /dev/null +++ b/lessons/beginners/str-methods/info.yml @@ -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 diff --git a/lessons/beginners/str/index.md b/lessons/beginners/str/index.md index 89398a5054..db66ed4762 100644 --- a/lessons/beginners/str/index.md +++ b/lessons/beginners/str/index.md @@ -1,353 +1,317 @@ -# Řetězce +# Zápis řetězců -Teď se podíváme na zoubek řetězcům (angl. *strings*). -Už víš, jak je zapisovat: +Teď se podíváme na zoubek řetězcům. +Už s nimi trochu umíš, tak začneme rekapitulací. + +Textový *řetězec* (angl. *string*) je datový typ (druh *hodnot*), +který obsahuje text – třeba slovo nebo větu. + +Když řetězec zadáváš do programu, musíš ho označit – uzavřít do +*uvozovek*, buď jednoduchých nebo dvojitých: ```python 'tohle je řetězec' "tohle taky" ``` -Někdy potřebuješ řetězce, které obsahují více řádků. -Pythonní řetězce ale můžeš normálně napsat jen na jeden řádek. -Jinak by koncová uvozovka mohla být kdekoli -a špatně by se hledala, kdybys na ni zapomněl{{a}}. +Je velký rozdíl mezi `print('cislo')` – vypiš slovo „cislo“ – +a `print(cislo)` – vypiš hodnotu výrazu `cislo`. +Jednou je `cislo` pět konkrétních písmen; podruhé *instrukce* k použití +proměnné. +Počítač, na rozdíl od lidí, rozdíl mezi textem a instrukcí nepozná z kontextu, +a tak je uvozovky potřeba používat důsledně. -Můžeš ale do řetězce znak pro nový řádek vložit pomocí speciálního -zápisu `\n`: +{{ figure( + img=static('quote-comic.svg'), + alt='(Ilustrační komiks. Člověk říká robotovi: "Řekni Pavlovi, ať mi zavolá!". Robot odpoví: "PAVLOVI AŤ MI ZAVOLÁ!")', +) }} -```python -print('Haló haló!\nCo se stalo?') -``` -Obecně zpětné lomítko umožňuje zapsat znaky, které by se špatně zadávaly. -Třeba uvozovka se dá zapsat jako `\"` a „apostrof“ jako `\'`. -To se dá použít, když potřebuješ mít v jednom -řetězci uvozovku i apostrof: +## Znaky -```python -print("Vtom vnuk křik': \"Hleď!\"") -print('"Jen ho nech," řek\' děd. "Kdo zná líp kraj?"') -``` +Texty sestávají z jednotlivých písmenek. +Řetězce víceméně taky, ale aby bylo jasné, co přesně tím *písmenkem* +myslíme, říkáme, že řetězce sestávají ze *znaků* (angl. *characters*). -Zpětným lomítkem se dají přidávat i -exotické znaky, které nemáš na klávesnici. -Ty se dají zapsat jako `\N` a jméno znaku -v složených („kudrnatých“) závorkách. -Třeba následující znaky. -(Do konzole na Windows bohužel nemusí jít všechny -vypsat, ale aspoň první by jít měl): +Takový znak může být písmenko (např. `A`) nebo číslice (`3`), +ale i jiný symbol (`!`). -```python -print('--\N{LATIN SMALL LETTER L WITH STROKE}--') -print('--\N{SECTION SIGN}--') -print('--\N{PER MILLE SIGN}--') -print('--\N{BLACK STAR}--') -print('--\N{SNOWMAN}--') -print('--\N{KATAKANA LETTER TU}--') +Každý řetězec má určitý počet znaků. +Kolik, to zjistíš pomocí funkce `len()`. +Třeba řetězec `Ahoj!` má znaků pět: + +```pycon +>>> len('Ahoj!') +5 ``` -Tahle vychytávka má jeden, někdy nepříjemný, -důsledek: pokud chceš použít zpětné lomítko -(třeba ve jménech souborů na Windows), -musíš ho ve zdrojovém kódu zdvojit. -Sekvence `\\` znamená „jedno zpětné lomítko“. +Jeden ze zajímavějších znaků je *mezera*. +Je to taky znak. V řetězci se tedy chová stejně jako písmenko: -```python -print('C:\\PyLadies\\Nový adresář') +```pycon +>>> len(' ') +1 +>>> len('K ní') +4 +>>> len('3 + 2') +5 ``` -Ale zpátky k řetězcům na více řádků. Kromě `\n` je i druhý způsob, jak takový -řetězec zadat: ohraničit ho *třemi* uvozovkami (jednoduchými nebo dvojitými) -na každé straně: +Mimochodem, řetězec může být i prázdný – pak má nula znaků: -```python -basen = '''Haló haló! -Co se stalo? -Prase kozu potrkalo!''' +```pycon +>>> len('') +0 +>>> len("") +0 ``` -Takové dlouhé texty nachází uplatnění třeba v dokumentačních řetězcích -u funkcí. -```python -def vynasob(a, b): - """Vynásobí argumenty a vrátí výsledek. +## Uvozovky - Oba argumenty by měly být čísla. - """ +K uvození řetězce můžeš použít jednoduché nebo dvojité rovné uvozovky. +Není mezi nimi rozdíl. +Podobně `4.0` a `4.000` jsou dva zápisy téhož čísla, +tak `'slovo'` a `"slovo"` pro Python označuje stejnou +hodnotu, skládající se ze stejných pěti písmen. - return a * b +Použité uvozovky nejsou součástí hodnoty – python si „nepamatuje“, jakým +způsobem byl řetězec uvozen. +Když má nějaký řetězec vypsat s uvozovkami, jedny si k tomu vybere – většinou +ty jednoduché: + +```pycon +>>> "python" +'python' +>>> 'slovo' +'slovo' ``` -Jen pozor na to, že pokud je tenhle řetězec -v odsazeném kódu, každý jeho řádek bude začínat -několika mezerami. -(V dokumentačních řetězcích to nevadí, tam se s odsazením počítá.) +> [note] +> Předchozí příklad je z interaktivního režimu Pythonu, který ukazuje hodnoty +> výrazů „programátorsky“ – pokud možno tak, jak se zapisují v Pythonu. +> Funkce `print()` vypisuje hodnoty „hezky“, „pro uživatele“ – v případě +> řetězců tedy bez uvozovek. -Tolik k zápisu řetězců. -Teď se podíváme, jak se zadanými řetězci pracovat. +### Uvozovky v uvozovkách -## Výběr znaků +Proč si při zadávání textu můžeš vybrat mezi dvěma druhy uvozovek? -Už umíš spojovat dohromady kratší řetězce: +Občas se stane, že v rámci textu potřebuješ použít samotnou uvozovku (nebo +apostrof). +Pak musíš „kolem“ řetězce použít tu druhou: ```python -spojeny_retezec = 'a' + 'b' -dlouhy_retezec = 'ó' * 100 +print('Zpívala si: "Tralala!"') +print("Byl to Goa'uld, parazit z planety P3X-888") ``` -Teď se podíváme na opačný proces: jak z dlouhého -řetězce dostat kratší součásti. -Začneme jednotlivými znaky. -Dělá se to operací *vybrání prvku* (angl. *subscripting*), -která se píše podobně jako volání funkce, jen s hranatými závorkami: -```python -pate_pismeno = 'čokoláda'[5] +Když v rámci textu použiješ stejnou uvozovku jako „kolem něj“, tak bude Python +naprosto zmatený. -print(pate_pismeno) +```pycon +>>> len("Zpívala si: "Tralala"") +Traceback (most recent call last) + File "<>", line 1 + len("Zpívala si: "Tralala"") + ^ +SyntaxError: invalid syntax ``` -Funguje to? Dostal{{a}} jsi opravdu páté písmeno? - -{% filter solution %} -Nedostal{{a}} – dostal{{a}} jsi *šesté* písmeno. -{% endfilter %} +Pokud používáš chytrý editor, doporučuju si zvyknout na to, jakou barvou +máš řetězce zvýrazněné. +Často to pomáhá odhalit chybky. -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 s písmeny v řetězcích: první písmeno má číslo nula, -druhé jedna, ... a osmé písmeno má číslo sedm. +## Sekvence se zpětným lomítkem -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í. +Co dělat, když v řetězci potřebuješ *oba* druhy uvozovek, +jako ve větě `Vtom vnuk křik': "Hleď!"`? -A nebo že mají rádi divná čísla jako nulu. +Můžeš si pomoci tím, že spojíš dva řetězce: -```plain - [0] [1] [2] [3] [4] [5] [6] [7] - - ╭───┬───┬───┬───┬───┬───┬───┬───╮ - │ Č │ o │ k │ o │ l │ á │ d │ a │ - ╰───┴───┴───┴───┴───┴───┴───┴───╯ +```pycon +>>> print("Vtom vnuk křik': " + '"Hleď!"') +Vtom vnuk křik': "Hleď!" ``` +Ale lepší způsob je použít speciální zápis se *zpětným lomítkem*. +Kdykoli se v řetězci objeví sekvence `\'` nebo `\"`, Python dá do řetězce danou +uvozovku. -A když už jsme u divných čísel, -co se asi stane, když budu chtít 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 +```pycon +>>> print("Vtom vnuk křik': \"Hleď!\"") +Vtom vnuk křik': "Hleď!" +>>> print('"Jen ho nech," řek\' děd. "Kdo zná líp kraj?"') +"Jen ho nech," řek' děd. "Kdo zná líp kraj?" ``` -Záporná čísla vybírají písmenka od konce. +Ve výsledném řetězci pak ovšem žádné zpětné lomítko *není*. +Sekvence `\'` je jen způsob, jak v Pythonu zadat `'` – jediný znak. +Tomu je celkem důležité porozumět. +Zkus si, jestli zvládneš předpovědět výsledek těchto výrazů: -```plain - [0] [1] [2] [3] [4] [5] [6] [7] - [-8][-7][-6][-5][-4][-3][-2][-1] - ╭───┬───┬───┬───┬───┬───┬───┬───╮ - │ Č │ o │ k │ o │ l │ á │ d │ a │ - ╰───┴───┴───┴───┴───┴───┴───┴───╯ +```pycon +>>> print(".\".") +>>> len(".\".") +>>> ".\"." ``` -{% endfilter %} - -Řetězce umí i jiné triky. -Třeba můžeš zjistit, jak je řetězec dlouhý -nebo jestli v sobě obsahuje daný menší řetězec. - - - - - - - - - - - - - - - - - - - - - - -
ZápisPopisPříklad
len(r)Délka řetězcelen('čokoláda')
x in rTrue pokud je řetězec x obsažen v r'oko' in 'čokoláda'
x not in rOpak x in r'dub' not in 'čokoláda
- -Ř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. -```python -retezec = 'Ahoj' -print(retezec.upper()) -print(retezec.lower()) -print(retezec) +{% filter solution %} +```pycon +>>> print(".\".") +.". +>>> len(".\".") +3 +>>> ".\"." +'.".' ``` +{% endfilter %} -> [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ý. +Znaků, které se zadávají sekvencí se zpětným lomítkem, je více. +Jedna ze zajímavějších je `\t`, představující tabulátor – jediný znak, který +se, když ho vypíšeš, „roztáhne“ na víc mezer. -### Iniciály +```pycon +>>> print("a\tb") # Výpis "pro lidi" +a b +>>> "a\tb" # Výpis "pro programátory" +'a\tb' +>>> len("a\tb") # Počet znaků v řetězci +3 +``` -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. +Se zpětným lomítkem se dá zadat jakýkoli znak – včetně *emoji* – podle jména +(`\N{…}`) nebo identifikačního čísla (`\x..`, `\u....`, `\U........`) +standardu Unicode. +Stačí přesné jméno nebo číslo znát (nebo třeba dohledat na internetu). +V následujících řetězcích jsou takové znaky pro přehlednost mezi dvěma +pomlčkami `-`. Délka každého řetězce je tedy celkem 3: + +```pycon +>>> print('-\N{GREEK CAPITAL LETTER DELTA}-') +-Δ- +>>> print('-\N{SECTION SIGN}-') +-§- +>>> print('-\N{GRINNING CAT FACE WITH SMILING EYES}-') +-😸- +>>> print('-\x60-') +-`- +>>> print('-\u30C4-') +-ツ- +>>> print('-\U0001F0BD-') +-🂽- +``` -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ětné lomítko -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í. +Zpětné lomítko tedy začíná speciální sekvenci (známou pod anglickým +termínem *escape sequence*), kterou zadáš *jediný znak*. -Nebo to jde zapsat i takto – -metoda se dá volat na výsledku jakéhokoli výrazu: +Tahle vychytávka má jeden, někdy nepříjemný, důsledek: pokud chceš mít jako +součást řetězce zpětné lomítko (třeba ve jménech souborů na Windows), +nemůžeš použít přímo `\`. +Musíš použít speciální sekvenci `\\` – tedy lomítko zdvojit: ```python -jmeno = input('Zadej jméno: ') -prijmeni = input('Zadej příjmení ') -print('Iniciály:', (jmeno[0] + prijmeni[0]).upper()) +print('C:\\PyLadies\\Nový adresář') ``` -Doporučuji spíš první způsob, ten se smysluplnými názvy proměnných. -Je sice delší, ale mnohem přehlednější. -{% endfilter %} - -Ř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. - -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áš). +Podobně jako `\"` je zápis pro uvozovku a `\'` pro apostrof, sekvence `\\` +je zápis pro jedno zpětné lomítko. -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áš. +### Nový řádek -## Sekání řetězců +Někdy potřebuješ řetězce, které obsahují více řádků. +Pythonní řetězce ale můžeš normálně napsat jen na *jeden* řádek. +(Python se tak snaží ulehčit hledání chyby, kdybys koncovou uvozovku +zapoměl{{a}}.) -Teď se vrátíme k vybírání kousků řetězců. -Zkus, co dělá tenhle program: +Můžeš ale do řetězce znak pro nový řádek vložit pomocí sekvence `\n`: -```python -retezec = 'čokoláda' -kousek = retezec[5:] -print(kousek) +```pycon +>>> print('Haló haló!\nCo se stalo?') +Haló haló! +Co se stalo? ``` -{% filter solution %} -Zápis `retezec[5:]` vybere *podřetězec* od znaku číslo 5 dál. -{% endfilter %} +Ono `\n` do řetězce vloží znak nového řádku. +Ten při výpisu ukončí stávající řádek a přejde na nový – ale jinak se chová +jako jakýkoli jiný znak: - -Dá se použít i `retezec[:5]`, -který vybere všechno *až po* znak číslo 5. -Ale ne znak 5 samotný, takže `retezec[:5] + retezec[5:] == retezec`. +```pycon +>>> print('-\n-') +- +- +>>> len('-\n-') +3 +``` -Co asi udělá `retezec[2:5]`? +## Trojité uvozovky -A co `retezec[-4:]`? +Kromě `\n` je i druhý způsob, jak zadat řetězec se znakem nového řádku: +ohraničit ho *třemi* uvozovkami (jednoduchými nebo dvojitými) +na každé straně. +Dají se tak zadávat delší víceřádkové řetězce: ```python -retezec = 'čokoláda' -print(retezec[:4]) -print(retezec[2:5]) -print(retezec[-4:]) +basen = '''Haló haló! +Co se stalo? +Prase kozu potrkalo!''' ``` -Určování vhodných čísel, *indexů*, občas vyžaduje trochu zamyšlení. - -U podobného „sekání“ (angl. *string slicing*) -je lepší si číslovat „hranice“ mezi znaky. -Člověk tomu pak lépe rozumí: - -{{ 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 +Víceřádkové řetězce se často používají jako dokumentační řetězce funkcí: - ╰───────────────╯ - 'čokoláda'[:4] == 'čoko' +```python +def vynasob(a, b): + """Vynásobí argumenty a vrátí výsledek. - ╰───────────────╯ - 'čokoláda'[2:6] == 'kolá' + Oba argumenty by měly být čísla. + """ - ╰───────────╯ - 'čokoláda'[-3:] == 'áda' + return a * b ``` +Pozor na to, že pokud je tenhle řetězec +v odsazeném kódu, každý jeho řádek bude začínat +několika mezerami. +(V dokumentačních řetězcích tohle nevadí, tam se s odsazením počítá.) -## 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ř: -```python -zamen('palec', 0, 'v') == 'valec' -zamen('valec', 2, 'j') == 'vajec' -``` - -Pozor na to, že řetězce v Pythonu nelze měnit. -Musíš vytvořit nový řetězec poskládaný z částí toho starého. +## Cvičení -{% filter solution %} -```python -def zamen(retezec, pozice, znak): - """Zamění znak na dané pozici +Jaká je délka těchto řetězců? - Vrátí řetězec, který má na dané pozici daný znak; - jinak je stejný jako vstupní retezec - """ +Výsledek zjistíš snadno, zkus se ale zamyslet a Python použít jen pro ověření. - return retezec[:pozice] + znak + retezec[pozice + 1:] +{# Highlighted as plain text to avoid spoilers #} +```plain +{# 2, 3, 4, 5 -#} +print(len('ahoj')) +print(len("""Ahoj!""")) +print(len('a b')) +print(len( ' a b ' )) +print(len('\N{SNOWMAN}ové')) +print(len('a\nb')) +print(len('a\tb')) +print(len('"\'"')) + +{# 3, 4, 5, 6 #} +print(len(""" +abc""")) + +{# 3, 5, 7, 9 #} +if True: + print(len("""a + b""")) + +{# 7, 8, 9, more #} +print(len('C:\new_dir')) + +print(len(f'{print}')) ``` -{% endfilter %} diff --git a/lessons/beginners/str/info.yml b/lessons/beginners/str/info.yml index 65928d387f..9254b1d1fb 100644 --- a/lessons/beginners/str/info.yml +++ b/lessons/beginners/str/info.yml @@ -1,6 +1,6 @@ -title: Řetězce +title: Zápis řetězců style: md attribution: -- Pro PyLadies Brno napsal Petr Viktorin, 2014-2017. +- Pro PyLadies Brno napsal Petr Viktorin, 2014-2019. - Jako jeden z příkladů byl použit úryvek z povídky „Chlap, děd, vnuk, pes a hrob“ Jana Wericha. license: cc-by-sa-40 diff --git a/lessons/beginners/str/static/quote-comic.svg b/lessons/beginners/str/static/quote-comic.svg new file mode 100644 index 0000000000..cd80509d62 --- /dev/null +++ b/lessons/beginners/str/static/quote-comic.svg @@ -0,0 +1,466 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +