NOVINKA: Získej 40 hodin praktických dovedností s AI – ZDARMA ke každému akreditovanému kurzu!
Hledáme nové posily do ITnetwork týmu. Podívej se na volné pozice a přidej se do nejagilnější firmy na trhu - Více informací.

Lekce 14 - Textové řetězce v Pythonu podruhé - Práce se znaky

V minulé lekci, Nejčastější chyby Python nováčků - Umíš pojmenovat proměnné?, jsme si ukázali nejčastější chyby začátečníků v Pythonu ohledně pojmenování proměnných.

V dnešním Python tutoriálu dále rozšíříme své znalosti řetězců. Naučíme se jejich porovnávání a řezání. Popíšeme si také nejdůležitější metody, které k práci s řetězci budeme často potřebovat.

Porovnávání řetězců

Řetězce se dají porovnávat pomocí standardních operátorů, které už dobře známe z předchozích lekcí:

Operátor Zápis
Rovnost ==
Je ostře větší >
Je ostře menší <
Je větší nebo rovno >=
Je menší nebo rovno <=
Nerovnost !=
Obecná negace not

Řetězce se porovnávají podle abecedy. Přesněji řečeno tak, že se vezmou postupně jednotlivé znaky porovnávaných řetězců a porovnají se pomocí funkce ord(). Tudíž znak a je menší než b, jelikož číselná hodnota a je 97 a číselná hodnota b je 98. Podívejme se na příklady:

Klikni pro editaci
  • print("a" < "b")
    print("b" < "a")
    print("c" == "c")
    print("ab" >= "a")
    print("e" <= "df")
    print("java" == "javascript")
    print("python" != "php")
    • Zkontroluj, zda výstupy programu odpovídají předloze. S jinými texty testy neprojdou.

    Řetězce se v Pythonu porovnávají znak po znaku zleva doprava. Takže i když je ve výrazu "e" <= "df" písmeno f větší než e, Python se na f ani nedívá, protože už našel rozdíl mezi prvními znaky řetězců (e a d). Je to podobné, jako když porovnáváme slova v abecedním pořádku. Například "slon" je dle abecedy před "zebrou".

    Řezání

    Z řetězců lze stejně jako ze seznamů extrahovat jednotlivé prvky. K tomuto účelu se používají hranaté závorky. Syntaxe je totožná jako u seznamů. Platí, že řetězec můžeme chápat jako seznam znaků:

    • seznam[m] – Vybere jediný znak.
    • seznam[m:n] – Vybere znaky v rozsahu mn-1.
    • seznam[m:n:i] – Vybere m a každý i-tý znak do n-1.

    Samozřejmě lze využít i speciality jako [:], která vybere celý řetězec, nebo [::-1], která řetězec převrátí. Ukažme si příklad řezání řetězce:

    Klikni pro editaci
    • retezec = "Honolulu"
      print(retezec[0])
      print(retezec[1:4])
      print(retezec[::2])
      print(retezec[3:9:2])
      • Zkontroluj, zda výstupy programu odpovídají předloze. S jinými texty testy neprojdou.

      V konzoli uvidíme výstup:

      Výstup řezání řetězce:
      H
      ono
      Hnll
      ouu

      Metody pro práci s řetězci

      Řetězce na sobě mají mnoho užitečných metod, díky nimž lze řetězce jednoduše upravovat. Zde si uvedeme metody, které se využívají velmi často. Nejprve ale malé upřesnění. S funkcemi i metodami jsme se již setkali.

      Rozdíl mezi nimi je ten, že funkce (mimo těch, které se později naučíme psát sami) jsou součástí programového jádra Pythonu. Metoda je pak funkce definovaná uvnitř třídy a volaná pro objekt.

      Objekty se budeme zabývat dále v kurzu Objektově orientovaného programování v Pythonu.

      Metoda count()

      Metoda vrátí počet podřetězců v jiném řetězci. Parametrem je hledaný podřetězec:

      Klikni pro editaci
      • retezec = "alabama"
        print(retezec.count("a"))
        print(retezec.count("a", 1, 4)) # Totéž jako retezec[1:4].count("a")
        • Zkontroluj, zda výstupy programu odpovídají předloze. S jinými texty testy neprojdou.

        Metoda find()

        Metoda nám vrátí index první pozice podřetězce v jiném řetězci. Hledaný podřetězec předáváme jako parametr. Pokud není podřetězec nalezen, metoda vrátí -1:

        Klikni pro editaci
        • retezec = "Wolfgang Amadeus Mozart"
          print(retezec.find("Wolfgang"))
          print(retezec.find("Beethoven"))
          • Zkontroluj, zda výstupy programu odpovídají předloze. S jinými texty testy neprojdou.

          Metoda index()

          Tato metoda je velmi podobná předchozí metodě find(), avšak pokud podřetězec nenalezne, vyvolá výjimku:

          Klikni pro editaci
          • retezec = "Wolfgang Amadeus Mozart"
            print(retezec.index("Wolfgang"))
            try:
                print(retezec.index("Beethoven"))
            except ValueError:
                print("Podřetězec nebyl nalezen!")
            • Zkontroluj, zda výstupy programu odpovídají předloze. S jinými texty testy neprojdou.

            Konstrukce try:except: slouží v Pythonu k zachycení výjimky. Více se tématu budeme věnovat dále v kurzu.

            Metoda isalpha()

            Metoda nám vrátí hodnotu True, pokud jsou všechny znaky v řetězci písmenné znaky a řetězec obsahuje minimálně jeden znak. V opačném případě metoda vrátí False:

            Klikni pro editaci
            • prvni_retezec = "Airbus"
              print(prvni_retezec.isalpha())
              druhy_retezec = "Boeing 737"
              print(druhy_retezec.isalpha())
              • Zkontroluj, zda výstupy programu odpovídají předloze. S jinými texty testy neprojdou.

              Metoda isdigit()

              Tato metoda vrátí True, pokud jsou všechny znaky v řetězci číselné znaky (09) a řetězec obsahuje minimálně jeden znak. Pokud tato podmínka není splněna, metoda vrátí False:

              Klikni pro editaci
              • prvni_retezec = "123"
                print(prvni_retezec.isdigit())
                druhy_retezec = "boeing737"
                print(druhy_retezec.isdigit())
                • Zkontroluj, zda výstupy programu odpovídají předloze. S jinými texty testy neprojdou.

                Metoda islower()

                Metoda vrátí True, pokud jsou všechny znaky v řetězci malá písmena a řetězec obsahuje minimálně jeden znak:

                Klikni pro editaci
                • prvni_retezec = "arizona"
                  print(prvni_retezec.islower())
                  druhy_retezec = "AriZona"
                  print(druhy_retezec.islower())
                  • Zkontroluj, zda výstupy programu odpovídají předloze. S jinými texty testy neprojdou.

                  Metoda isupper()

                  Metoda vrátí True, pokud jsou všechny znaky v řetězci velká písmena a řetězec obsahuje minimálně jeden znak:

                  Klikni pro editaci
                  • prvni_retezec = "ARIZONA"
                    print(prvni_retezec.isupper())
                    druhy_retezec = "arizona"
                    print(druhy_retezec.isupper())
                    • Zkontroluj, zda výstupy programu odpovídají předloze. S jinými texty testy neprojdou.

                    Další metody pro práci s řetězci si můžeme prohlédnout po zadání příkazu help(str) v konzoli.

                    Využití znalostí práce s řetězci v praxi

                    O řetězcích už víme poměrně dost. Pojďme si tedy naše znalosti vyzkoušet v praxi na třech zajímavých programech.

                    Analýza výskytu znaků ve větě

                    Napišme si jednoduchý program, který nám zanalyzuje zadanou větu. Bude nás zajímat počet samohlásek, souhlásek a počet nepísmenných znaků (např. mezera nebo !).

                    Řetězec budeme projíždět cyklem po jednom znaku. Neapelujeme na rychlost programu a budeme volit názorná a jednoduchá řešení.

                    Protože se jedná o složitější kód, nebudeme zapomínat na komentáře.

                    Nejprve od uživatele získáme vstupní řetězec, který budeme analyzovat. Abychom nemuseli řešit velikost písmen, celý řetězec na začátku převedeme na malá písmena. Připravíme si proměnné s výchozími hodnotami a definujeme si samohlásky, souhlásky a čísla. Počet ostatních znaků pak bude vše, co zbude. V hlavním cyklu budeme větu procházet znak po znaku. Pokaždé rozhodneme, do které kategorie znak patří. Podle toho pak budeme ukládat jednotlivé počty do odpovídajících proměnných:

                    Klikni pro editaci
                    • print("Program zjistí, z čeho se skládá věta.")
                      zadana_veta = input("Zadejte větu: ")
                      
                      # Převedeme větu na malá písmena. Původní větu si ponecháme v proměnné zadana_veta beze změny
                      veta = zadana_veta.lower()
                      
                      #  Nastavíme výchozí počty proměnných
                      samohlasky = 0
                      souhlasky = 0
                      ostatni = 0
                      cisel = 0
                      
                      #  Definujeme sady typů znaků
                      samohlasky_sada = "aáeéěiíoóuúůyý"
                      souhlasky_sada = "bcčdďfghjklmnňpqrřsštťvwxzž"
                      cisla_sada = "0123456789"
                      
                      #  V hlavním cyklu programu analyzujeme druh a počet znaků
                      for znak in veta:
                          if znak in samohlasky_sada:      # Nejprve samohlásky
                              samohlasky += 1
                          elif znak in souhlasky_sada:     # Pak souhlásky
                              souhlasky += 1
                          elif znak in cisla_sada:         # Poté čísla
                              cisel += 1
                          else:
                              ostatni += 1        # Vše, co zbylo, jsou ostatní znaky (mezery, tečky atd...)
                      
                      # Zde využijeme původní nezměněnou větu
                      print(f'Vaše věta: "{zadana_veta}" má:')
                      print("samohlásek:", samohlasky)
                      print("souhlásek:", souhlasky)
                      print("čísel:", cisel)
                      print("ostatních znaků:", ostatni)
                      
                      input("\nAplikaci ukončíte stisknutím klávesy Enter...")
                      • Zkontroluj, zda výstupy programu odpovídají předloze. S jinými texty testy neprojdou.

                      Výstup programu:

                      Výstup programu analýzy věty:
                      Program zjistí, z čeho se skládá věta.
                      Zadejte větu: Nejvýznamnější z novobabylonských králů Nabuchodonozor II. vládl v letech 605 až 562 př. n. l.
                      Vaše věta: "Nejvýznamnější z novobabylonských králů Nabuchodonozor II. vládl v letech 605 až 562 př. n. l." má:
                      samohlásek: 25
                      souhlásek: 45
                      čísel: 6
                      ostatních znaků: 18
                      
                      Aplikaci ukončíte stisknutím klávesy Enter...

                      Zápis samohlasky += 1 je zkrácená verze samohlasky = samohlasky + 1. V Pythonu se tento zápis používá naprosto běžně ke zkrácení operací s proměnnými. Analogicky funguje i s ostatními operátory (např. -=, *=, /= atd.).

                      ASCII hodnota

                      Nyní se blíže podíváme na ASCII tabulku. Zejména v éře operačního systému MS-DOS prakticky nebyla jiná možnost, jak zaznamenávat text. Jednotlivé znaky byly uloženy jako čísla typu byte, tedy s rozsahem hodnot od 0 do 255. V systému byla uložena tzv. ASCII tabulka, která měla 256 znaků a každému ASCII kódu (číselnému kódu) přiřazovala jeden znak.

                      Tento způsob neměl šanci přetrvat dodnes. Do tabulky se jednoduše nevejdou všechny znaky všech národních abeced. Nyní se používá Unicode (UTF-8) kódování, kde jsou znaky reprezentovány trochu jiným způsobem. V Pythonu přesto máme možnost pracovat s ASCII hodnotami jednotlivých znaků. Hlavní výhoda spočívá v tom, že znaky jsou uloženy v tabulce za sebou podle abecedy. Například na pozici 97 nalezneme 'a', na 98 zase 'b' a podobně. Stejné je to s čísly. Diakritické znaky jsou v ASCII hodnotách bohužel jen nějak rozházené.

                      Zkusme si nyní převést znak do jeho ASCII hodnoty a naopak podle ASCII hodnoty daný znak vytvořit:

                      Klikni pro editaci
                      • print(ord("a"))
                        print(chr(97))
                        • Zkontroluj, zda výstupy programu odpovídají předloze. S jinými texty testy neprojdou.

                        V konzoli uvidíme výstup:

                        Převod znaku na ASCII a zpět:
                        97
                        a

                        K získání ordinální (ASCII) hodnoty znaku jsme použili funkci ord(). Pomocí funkce chr() jsme naopak získali znak z jeho ordinální hodnoty.

                        Caesarova šifra

                        Vytvoříme si jednoduchý program pro šifrování textu. Pokud jste někdy slyšeli o Caesarově šifře, bude to přesně to, co si zde naprogramujeme. Šifrování textu spočívá v posouvání znaku v abecedě o určitý, pevně stanovený počet znaků. Například slovo ahoj se s posunem textu o 1 přeloží jako bipk. Posun umožníme uživateli vybrat. Algoritmus máme detailně vysvětlený v článku Caesarova šifra. Program si dokonce můžeme už teď vyzkoušet v praxi – Online Caesarova šifra.

                        Vraťme se ale k programování a připravme si kód. Budeme potřebovat proměnné pro původní text, pro zašifrovanou zprávu a pro posun. Dále budeme potřebovat vytvořit cyklus procházející jednotlivé znaky a cyklus pro výpis zašifrované zprávy. Zprávu si nejprve necháme zapsanou napevno v kódu, abychom ji nemuseli při každém spuštění programu psát znovu. Po dokončení nahradíme obsah proměnné funkcí input(). Šifra nepočítá s diakritikou, mezerami a interpunkčními znaménky. Diakritiku budeme bojkotovat :-) a budeme předpokládat, že ji uživatel nebude zadávat. Ideálně bychom poté měli diakritiku i všechny ostatní znaky kromě písmen před šifrováním odstranit. Pojďme na to:

                        # Inicializace proměnných
                        retezec = "gaiusjuliuscaesar"
                        print("Původní zpráva:", retezec)
                        zprava = ""
                        posun = 1
                        
                        # Cyklus projíždějící jednotlivé znaky
                        for znak in retezec:
                            pass         # Klíčové slovo pass se v Pythonu používá mj. pro prozatímně prázdný cyklus. Více se o něm dovíme později v kurzu.
                        # Výpis
                        print("Zašifrovaná zpráva:", zprava)
                        input()

                        Nyní se přesuneme dovnitř cyklu. V něm převedeme znak na ASCII hodnotu (neboli ordinální hodnotu). Tuto hodnotu zvýšíme o posun a převedeme zpět na znak. Tento znak nakonec připojíme k výsledné zprávě:

                        Klikni pro editaci
                        • # Cyklus projíždějící jednotlivé znaky
                          for znak in retezec:
                              i = ord(znak)
                              i = i + posun
                              znak = chr(i)
                              zprava = zprava + znak
                          
                          • Zkontroluj, zda výstupy programu odpovídají předloze. S jinými texty testy neprojdou.

                          Program si vyzkoušíme. Výsledek v konzoli vypadá docela dobře:

                          Caesarova šifra:
                          Původní zpráva: gaiusjuliuscaesar
                          Zašifrovaná zpráva: hbjvtkvmjvtdbftbs

                          Zkusme si však zadat vyšší posun nebo napsat slovo zebra. Vidíme, že znaky mohou po z přetéct do ASCII hodnot dalších znaků, v textu tedy již nemáme jen písmena, ale také další ošklivé znaky. Uzavřeme proto znaky do kruhu tak, aby posun po z plynule přešel opět k a a dále. Postačí nám k tomu jednoduchá podmínka, která od nové ASCII hodnoty odečte celou abecedu tak, abychom začínali opět na a:

                          Klikni pro editaci
                          •     i = ord(znak)
                                i = i + posun
                                # kontrola přetečení
                                if (i > ord("z")):
                                    i = i - 26
                                znak = chr(i)
                                zprava = zprava + znak
                            
                            • Zkontroluj, zda výstupy programu odpovídají předloze. S jinými texty testy neprojdou.

                            V konzoli vidíme, že naše úprava funguje správně:

                            Caesarova šifra:
                            Původní zpráva: gaiusjuliuscaesar
                            Zašifrovaná zpráva: hbjvtkvmjvtdbftbs

                            Pokud i přesáhne ASCII hodnotu z, snížíme ho o 26 znaků (tolik znaků má anglická abeceda). Je to jednoduché a náš program je nyní funkční. Všimněme si, že nikde nepoužíváme přímé kódy znaků. V podmínce je ord("z"), i když bychom tam mohli napsat rovnou 122. Je to z důvodu, aby byl náš program plně odstíněn od explicitních ASCII hodnot a bylo lépe viditelné, jak funguje. Cvičně si zkuste udělat dešifrování :)

                            V následujícím cvičení, Řešené úlohy k 14. lekci Pythonu, si procvičíme nabyté zkušenosti z předchozích lekcí.


                             

                            Měl jsi s čímkoli problém? Stáhni si vzorovou aplikaci níže a porovnej ji se svým projektem, chybu tak snadno najdeš.

                            Stáhnout

                            Stažením následujícího souboru souhlasíš s licenčními podmínkami

                            Staženo 253x (1.88 kB)
                            Aplikace je včetně zdrojových kódů v jazyce Python

                             

                            Jak se ti líbí článek?
                            Před uložením hodnocení, popiš prosím autorovi, co je špatněZnaků 0 z 50-500
                            Předchozí článek
                            Nejčastější chyby Python nováčků - Umíš pojmenovat proměnné?
                            Všechny články v sekci
                            Základní konstrukce jazyka Python
                            Přeskočit článek
                            (nedoporučujeme)
                            Řešené úlohy k 14. lekci Pythonu
                            Článek pro vás napsal gcx11
                            Avatar
                            Uživatelské hodnocení:
                            1070 hlasů
                            (^_^)
                            Aktivity