Nauč se Python > Kurzy > „Experimentální“ začátečnický kurz PyLadies > Řetězce

Řetězce

Teď se podíváme na zoubek řetězcům (angl. strings). Už víš, jak je zapisovat:

'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ěla.

Můžeš ale do řetězce znak pro nový řádek vložit pomocí speciálního zápisu \n:

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:

print("Vtom vnuk křik': \"Hleď!\"")
print('"Jen ho nech," řek\' děd. "Kdo zná líp kraj?"')

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):

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}--')

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“.

print('C:\\PyLadies\\Nový adresář')

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ě:

basen = '''Haló haló!
Co se stalo?
Prase kozu potrkalo!'''

Takové dlouhé texty nachází uplatnění třeba v dokumentačních řetězcích u funkcí.

def vynasob(a, b):
    """Vynásobí argumenty a vrátí výsledek.

    Oba argumenty by měly být čísla.
    """

    return a * b

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á.)

Tolik k zápisu řetězců. Teď se podíváme, jak se zadanými řetězci pracovat.

Výběr znaků

Už umíš spojovat dohromady kratší řetězce:

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. 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:

pate_pismeno = 'čokoláda'[5]

print(pate_pismeno)

Funguje to? Dostala jsi opravdu páté písmeno?

Řešení

Jak sis možná už všimla, 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.

Proč je tomu tak? K úplnému pochopení důvodů by ses potřebovala 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í.

A nebo že mají rádi divná čísla jako nulu.

   [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 chtít vybírat písmena pomocí záporných čísel?

Řešení

Ř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ápis Popis Příklad
len(r) Délka řetězce len('čokoláda')
x in r True pokud je řetězec x obsažen v r 'oko' in 'čokoláda'
x not in r Opak 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ěla porovnávat bez ohledu na velikost písmen, musela 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.

retezec = 'Ahoj'
print(retezec.upper())
print(retezec.lower())
print(retezec)

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ý.

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).

Řešení

Řetězcových metod je celá řada. Nejužitečnější z nich najdeš v taháku, který si můžeš stáhnout či vytisknout.

A úplně všechny řetězcové metody jsou popsány v dokumentaci Pythonu (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áš.

Formátování

Obzvláště užitečná je metoda format, která v rámci řetězce nahradí dvojice „kudrnatých“ závorek za to, co dostane v argumentech:

vypis = '{}×{} je {}'.format(3, 4, 3 * 4)
print(vypis)

Řetězec '{}×{} je {}' tady funguje jako šablona (angl. template). Představ si to jako jako formulář, do kterého Python na vyznačená místa vpisuje hodnoty.

Pokud chceš nahradit hodnoty v jiném pořadí, nebo když chceš aby šablona byla čitelnější, můžeš do „kudrnatých“ závorek napsat jména:

vypis = 'Ahoj {jmeno}! Výsledek je {cislo}.'.format(cislo=7, jmeno='Elvíro')
print(vypis)

Formátování se používá skoro všude, kde je potřeba „hezky“ vypsat nějakou hodnotu.

Sekání řetězců

Teď se vrátíme k vybírání kousků řetězců. Zkus, co dělá tenhle program:

retezec = 'čokoláda'
kousek = retezec[5:]
print(kousek)

Řešení

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.

Co asi udělá retezec[2:5]?

A co retezec[-4:]?

retezec = 'čokoláda'
print(retezec[:4])
print(retezec[2:5])
print(retezec[-4:])

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í:

  ╭───┬───┬───┬───┬───┬───┬───┬───╮
  │ Č │ 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ř:

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.

Řešení