Zarábaj až 6 000 € mesačne! Akreditované rekvalifikačné kurzy od 0 €. Viac informácií.
Hľadáme nové posily do ITnetwork tímu. Pozri sa na voľné pozície a pridaj sa k najagilnejšej firme na trhu - Viac informácií.

13. diel - Textové reťazce v Pythone druhýkrát - Práca so znakmi

V minulej lekcii, Najčastejšie chyby Python nováčikov - Vieš pomenovať premenné? , sme si ukázali najčastejšie chyby začiatočníkov v Pythone ohľadom pomenovania premenných.

V dnešnom Python tutoriále ďalej rozšírime svoje znalosti reťazcov. Naučíme sa ich porovnávanie a rezanie. Popíšeme si tiež najdôležitejšie metódy, ktoré na prácu s reťazcami budeme často potrebovať.

Porovnávanie reťazcov

Reťazce sa dajú porovnávať pomocou štandardných operátorov, ktoré už dobre poznáme z predchádzajúcich lekcií:

Operátor Zápis
Rovnosť ==
Je ostro väčšia >
Je ostro menší <
Je väčšia alebo rovná >=
Je menšia alebo rovná <=
Nerovnosť !=
Všeobecná negácia !
Reťazce sa porovnávajú podľa abecedy. Presnejšie povedané tak, že sa vezmú postupne jednotlivé znaky porovnávaných reťazcov a porovnajú sa pomocou funkcie ord(). Preto znak a je menší ako b, pretože číselná hodnota a je 97 a číselná hodnota b je 98. Pozrime sa na príklady:
print("a" < "b")
print("b" < "a")
print("c" == "c")
print("ab" >= "a")
print("e" <= "df")
print("java" == "javascript")
print("python" != "php")

Reťazce sa v Pythone porovnávajú znak po znaku zľava doprava. Takže aj keď je vo výraze "e" <= "df" písmeno f väčšie ako e, Python sa na f ani nepozerá, pretože už našiel rozdiel medzi prvými znakmi reťazcov (e a d). Je to podobné, ako keď porovnávame slová v abecednom poriadku. Napríklad "slon" je podľa abecedy pred "zebrou".

Rezanie

Z reťazcov je možné rovnako ako zo zoznamov extrahovať jednotlivé prvky. Na tento účel sa používajú hranaté zátvorky. Syntax je totožná ako pri zoznamoch. Platí, že reťazec môžeme chápať ako zoznam znakov:

  • seznam[m] – Vyberie jediný znak.
  • seznam[m:n] – Vyberie znaky v rozsahu mn-1.
  • seznam[m:n:i] – Vyberie m a každý i -tý znak do n-1.
Samozrejme je možné využiť aj špeciality ako [:], ktorá vyberie celý reťazec, alebo [::-1], ktorá reťazec prevráti. Ukážme si príklad rezania reťazca:
retezec = "Honolulu"
print(retezec[0])
print(retezec[1:4])
print(retezec[::2])
print(retezec[3:9:2])

V konzole uvidíme výstup:

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

Metódy pre prácu s reťazcami

Reťazce na sebe majú mnoho užitočných metód, vďaka ktorým je možné reťazce jednoducho upravovať. Tu si uvedieme metódy, ktoré sa využívajú veľmi často. Najprv ale malé upresnenie. S funkciami aj metódami sme sa už stretli.

Rozdiel medzi nimi je ten, že funkcie (okrem tých, ktoré sa neskôr naučíme písať sami) sú súčasťou programového jadra Pythona. Metóda je potom funkcia definovaná vo vnútri triedy a volaná pre objekt.

Objekty sa budeme zaoberať ďalej v kurze Objektovo orientovaného programovania v Pythone.

Metóda count()

Metóda vráti počet podreťazcov v inom reťazci. Parametrom je hľadaný podreťazec:

retezec = "alabama"
print(retezec.count("a"))
print(retezec.count("a", 1, 4)) # To isté ako retezec[1:4].count("a")

Metóda find()

Metóda nám vráti index prvej pozície podreťazca v inom reťazci. Hľadaný podreťazec odovzdávame ako parameter. Ak nie je podreťazec nájdený, metóda vráti -1:

retezec = "Wolfgang Amadeus Mozart"
print(retezec.find("Wolfgang"))
print(retezec.find("Beethoven"))

Metóda index()

Táto metóda je veľmi podobná predchádzajúcej metóde find(), avšak pokiaľ podreťazec nenájde, vyvolá výnimku:

retezec = "Wolfgang Amadeus Mozart"
print(retezec.index("Wolfgang"))
try:
    print(retezec.index("Beethoven"))
except ValueError:
    print("Podřetězec nebyl nalezen!")

Konštrukcia try:except: slúži v Pythone na zachytenie výnimky. Viac sa téme budeme venovať ďalej v kurze.

Metóda isalpha()

Metóda nám vráti hodnotu True, ak sú všetky znaky v reťazci písmenné znaky a reťazec obsahuje minimálne jeden znak. V opačnom prípade metóda vráti False:

prvni_retezec = "Airbus"
print(prvni_retezec.isalpha())
druhy_retezec = "Boeing 737"
print(druhy_retezec.isalpha())

Metóda isdigit()

Táto metóda vráti True, ak sú všetky znaky v reťazci číselné znaky (09) a reťazec obsahuje minimálne jeden znak. Ak táto podmienka nie je splnená, metóda vráti False:

prvni_retezec = "123"
print(prvni_retezec.isdigit())
druhy_retezec = "boeing737"
print(druhy_retezec.isdigit())

Metóda islower()

Metóda vráti True, ak sú všetky znaky v reťazci malé písmená a reťazec obsahuje minimálne jeden znak:

prvni_retezec = "arizona"
print(prvni_retezec.islower())
druhy_retezec = "AriZona"
print(druhy_retezec.islower())

Metóda isupper()

Metóda vráti True, ak sú všetky znaky v reťazci veľké písmená a reťazec obsahuje minimálne jeden znak:

prvni_retezec = "ARIZONA"
print(prvni_retezec.isupper())
druhy_retezec = "arizona"
print(druhy_retezec.isupper())

Ďalšie metódy pre prácu s reťazcami si môžeme prezrieť po zadaní príkazu help(str) v konzole.

Využitie znalostí práce s reťazcami v praxi

O reťazcoch už vieme pomerne dosť. Poďme si teda naše znalosti vyskúšať v praxi na troch zaujímavých programoch.

Analýza výskytu znakov vo vete

Napíšme si jednoduchý program, ktorý nám zanalyzuje zadanú vetu. Bude nás zaujímať počet samohlások, spoluhlások a počet nepísmenných znakov (napr. medzera alebo !).

Reťazec budeme prechádzať cyklom po jednom znaku. Neapelujeme na rýchlosť programu a budeme voliť názorné a jednoduché riešenia.

Pretože sa jedná o zložitejší kód, nebudeme zabúdať na komentáre.

Najprv od používateľa získame vstupný reťazec, ktorý budeme analyzovať. Aby sme nemuseli riešiť veľkosť písmen, celý reťazec na začiatku prevedieme na malé písmená. Pripravíme si premenné s východiskovými hodnotami a definujeme si samohlásky, spoluhlásky a čísla. Počet ostatných znakov potom bude všetko, čo zostane. V hlavnom cykle budeme vetu prechádzať znak po znaku. Zakaždým rozhodneme, do ktorej kategórie znak patrí. Podľa toho potom budeme ukladať jednotlivé počty do zodpovedajúcich premenných:

print("Program zistí, z čoho sa skladá veta.")
zadana_veta = input("Zadajte vetu: ")

# 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ša veta: "{zadana_veta}" má:')
print("samohlások:", samohlasky)
print("spoluhlások:", souhlasky)
print("čísel:", cisel)
print("ostatných znakov:", ostatni)

input("\nAplikáciu ukončíte stlačením klávesu Enter...")

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 skrátená verzia samohlasky = samohlasky + 1. V Pythone sa tento zápis používa úplne bežne na skrátenie operácií s premennými. Analogicky funguje aj s ostatnými operátormi (napr. -=, *=, /= atď.).

ASCII hodnota

Teraz sa bližšie pozrieme na ASCII tabuľku. Najmä v ére operačného systému MS-DOS prakticky nebola iná možnosť, ako zaznamenávať text. Jednotlivé znaky boli uložené ako čísla typu byte, teda s rozsahom hodnôt od 0 do 255. V systéme bola uložená tzv. ASCII tabuľka, ktorá mala 256 znakov a každému ASCII kódu (číselnému kódu) priraďovala jeden znak.

Tento spôsob nemal šancu pretrvať dodnes. Do tabuľky sa jednoducho nezmestia všetky znaky všetkých národných abecied. Teraz sa používa Unicode (UTF-8) kódovanie, kde sú znaky reprezentované trochu iným spôsobom. V Pythone napriek tomu máme možnosť pracovať s ASCII hodnotami jednotlivých znakov. Hlavná výhoda spočíva v tom, že znaky sú uložené v tabuľke za sebou podľa abecedy. Napríklad na pozícii 97 nájdeme 'a', na 98 zase 'b' a podobne. Rovnaké je to s číslami. Diakritické znaky sú v ASCII hodnotách bohužiaľ len nejako rozhádzané.

Skúsme si teraz previesť znak do jeho ASCII hodnoty a naopak podľa ASCII hodnoty daný znak vytvoriť:

print(ord("a"))
print(chr(97))

V konzole uvidíme výstup:

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

Na získanie ordinálnej (ASCII) hodnoty znaku sme použili funkciu ord(). Pomocou funkcie chr() sme naopak získali znak z jeho ordinálnej hodnoty.

Caesarova šifra

Vytvoríme si jednoduchý program na šifrovanie textu. Ak ste niekedy počuli o Caesarovej šifre, bude to presne to, čo si tu naprogramujeme. Šifrovanie textu spočíva v posúvaní znaku v abecede o určitý, pevne stanovený počet znakov. Napríklad slovo ahoj sa s posunom textu o 1 preloží ako bipk. Posun umožníme užívateľovi vybrať. Algoritmus máme detailne vysvetlený v článku Caesarovho šifra. Program si dokonca môžeme už teraz vyskúšať v praxi - Online Caesarovho šifra.

Vráťme sa ale na programovanie a pripravme si kód. Budeme potrebovať premenné pre pôvodný text, pre zašifrovanú správu a pre posun. Ďalej budeme potrebovať vytvoriť cyklus prechádzajúci jednotlivé znaky a cyklus pre výpis zašifrovanej správy. Správu si najskôr necháme zapísanú napevno v kóde, aby sme ju nemuseli pri každom spustení programu písať znova. Po dokončení nahradíme obsah premennej funkcií input(). Šifra nepočíta s diakritikou, medzerami a interpunkčnými znamienkami. Diakritiku budeme bojkotovať:-) a budeme predpokladať, že ju užívateľ nebude zadávať. Ideálne by sme potom mali diakritiku aj všetky ostatné znaky okrem písmen pred šifrovaním odstrániť. Poďme na to:

# Inicializácia premenných
retezec = "gaiusjuliuscaesar"
print("Pôvodná správa:", retezec)
zprava = ""
posun = 1

# Cyklus prechádzajúci jednotlivými znakmi
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á správa:", zprava)
input()

Teraz sa presunieme dovnútra cyklu. V ňom prevedieme znak na ASCII hodnotu (čiže ordinálnu hodnotu). Túto hodnotu zvýšime o posun a prevedieme späť na znak. Tento znak nakoniec pripojíme k výslednej správe:

# Cyklus prechádzajúci jednotlivými znakmi
for znak in retezec:
    i = ord(znak)
    i = i + posun
    znak = chr(i)
    zprava = zprava + znak

Program si vyskúšame. Výsledok v konzole vyzerá celkom dobre:

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

Skúsme si však zadať vyšší posun alebo napísať slovo zebra. Vidíme, že znaky môžu po z pretiecť do ASCII hodnôt ďalších znakov, v texte teda už nemáme len písmená, ale aj ďalšie škaredé znaky. Uzavrieme preto znaky do kruhu tak, aby posun po z plynule prešiel opäť k a a ďalej. Postačí nám k tomu jednoduchá podmienka, ktorá od novej ASCII hodnoty odpočíta celú abecedu tak, aby sme začínali opäť na a:

    i = ord(znak)
    i = i + posun
    # kontrola pretečenia
    if (i > ord("z")):
        i = i - 26
    znak = chr(i)
    zprava = zprava + znak

V konzole vidíme, že naša úprava funguje správne:

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

Pokiaľ i presiahne ASCII hodnotu z, znížime ho o 26 znakov (toľko znakov má anglická abeceda). Je to jednoduché a náš program je teraz funkčný. Všimnime si, že nikde nepoužívame priame kódy znakov. V podmienke je ord("z"), aj keď by sme tam mohli napísať rovno 122. Je to z dôvodu, aby bol náš program plne odtienený od explicitných ASCII hodnôt a bolo lepšie viditeľné, ako funguje. Cvične si skúste urobiť dešifrovanie:)

V nasledujúcom cvičení, Riešené úlohy k 13. lekcii Pythonu, si precvičíme nadobudnuté skúsenosti z predchádzajúcich lekcií.


 

Mal si s čímkoľvek problém? Stiahni si vzorovú aplikáciu nižšie a porovnaj ju so svojím projektom, chybu tak ľahko nájdeš.

Stiahnuť

Stiahnutím nasledujúceho súboru súhlasíš s licenčnými podmienkami

Stiahnuté 108x (1.88 kB)
Aplikácia je vrátane zdrojových kódov v jazyku Python

 

Predchádzajúci článok
Najčastejšie chyby Python nováčikov - Vieš pomenovať premenné?
Všetky články v sekcii
Základné konštrukcie jazyka Python
Preskočiť článok
(neodporúčame)
Riešené úlohy k 13. lekcii Pythonu
Článok pre vás napísal gcx11
Avatar
Užívateľské hodnotenie:
8 hlasov
(^_^)
Aktivity