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 | ! |
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 rozsahum
ažn-1
.seznam[m:n:i]
– Vyberiem
a každýi
-tý znak don-1
.
[:]
, 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 (0
– 9
) 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:
# 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:
i = ord(znak)
i = i + posun
znak = chr(i)
zprava = zprava + znak
# Výpis
print("Zašifrovaná správa:", zprava)
input()
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
:
# 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:
i = ord(znak)
i = i + posun
# kontrola pretečenia
if (i > ord("z")):
i = i - 26
znak = chr(i)
zprava = zprava + znak
# Výpis
print("Zašifrovaná správa:", zprava)
input()
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