V minulém díle jste viděli…¶
Textový řetězec (string) je základní datový typ v Pythonu, používaný k uchování libovolných znaků, a to zpravidla textové informací. Stringy jsou neměnné (immutable) a hashovatelné, což znamená, že po provedení "modifikovatelné" operaci se vždy vytvoří nový string, původní se nemění. Stringy jsou instancemi třídy str
.
Stringy můžeme vytvořit pomocí jednoduchých (apostrofy), dvojitých uvozovek nebo jejich trojic. První dva způsoby jsou téměř ekvivalentní. Rozdíl se může objevit v případě použití uvozovek uvnitř textu.
s1 = "Potřebuji \n\"'apostrofy'"
s2 = 'Potřebuji "uvozovky"'
print(s1)
print(s2)
Potřebuji "'apostrofy' Potřebuji "uvozovky"
Poslední způsob se používá pro vytváření víceřádkových řetězců.
s3 = '''Jsem víceřádkový string,
vytvořený pomocí
trojic jednoduchých uvozovek.'''
print(s3)
Jsem víceřádkový string, vytvořený pomocí trojic jednoduchých uvozovek.
Použití escape sekvencí umožňuje vkládat speciální znaky do stringů, jako například nový řádek (\n
) nebo uvozovky (\"
). Escape sekvence se začínají zpětným lomítkem (\
).
Python umožňuje převádět stringy na jiné datové typy a zpět.
print(int("1234"))
print(float("-3.5"))
print(complex("1+2j"))
print(bool("False"))
print(str("Python"))
print(repr("Python"))
# na seznam a zpět
x = "abc"
l = list(x)
print(l)
s = str(l)
print(s)
s = "".join(l)
print(s)
# operátory + a *
a = "abc" + " " + "eg" * 3
print(a)
1234 -3.5 (1+2j) True Python 'Python' ['a', 'b', 'c'] ['a', 'b', 'c'] abc abc egegeg
Pro stringy je možné používat základní operace jako testování, iterování, zřetězení, porovnání. Jsou k dispozici i indexování a vykrajování (slicing). Porovnávání stringů se provádí znak po znaku podle jejich kódů. Pozor na výsledky porovnání, které mohou být ovlivněny znakovou sadou a velikostí písmen tzn. být jiné než v tradičním lexikografickém uspořádání.
# opakovani:
s = "abcdef ahoj!"
for x in s:
print(x, end = " ")
print("")
print(s[0])
#s[-1] = "2" # chyba!
s= "2" + s[1:]
print(s)
for i in range(len(s)):
print(s[i], end = " ")
print("")
c = "a"
if c in s:
print("ano, je tam")
print(s[2:4])
a b c d e f a h o j ! a 2bcdef ahoj! 2 b c d e f a h o j ! ano, je tam cd
Pro zpracování jednotlivých znaků se mohou používat funkce chr()
a ord()
. Funkce chr(i)
převádí celé číslo i
na znak, zatímco ord(c)
převádí znak c
na jeho kód v Unicode. Python nezavádí samostatný datový typ pro znaky, zadávají se jako stringy obsahující pouze jeden znak.
print(chr(0x20ac)) # Znak euro
print(chr(0x1D120)) # Houslový klíč
print(ord("€"))
x = "A"
y = ord(x)
print(x, y, chr(y))
print("a" < "A") # False
print(ord("a"), ord("A"))
print(sorted(["Ábc","Abc", "abc", "ABC"])) # setřídí stringy podle kódů (vzestupně)
print(sorted(["Ábc","Abc", "abc", "ABC"], reverse=True)) # setřídí stringy podle kódů (sestupně)
# vytvoří setříděný seznam znaků
print(sorted("abhjsdvkdgcvsdgcdsjkzdg"))
€ 𝄠 8364 A 65 A False 97 65 ['ABC', 'Abc', 'abc', 'Ábc'] ['Ábc', 'abc', 'Abc', 'ABC']
Textové řetězce (2. část)¶
Metody třídy str
¶
Typ str
v Pythonu je třída, a proto se během rozhovoru o textových řetězcích potřebujeme stručně seznámit s termínem metoda (anglicky method) z objektově orientovaného programování. Stringové metody jsou asi nejzajímavější částí, kterou budeme běžně používat v práci s textem.
Metody jsou sice stále funkce, ale protože jsou části třidy, interpret zachází s nimi maličko jinak. Při volání metody budeme používat tečkovou notaci textový_řetězec.název_metody()
. Pak interpret předá té metodě odkaz na textový_řetězec
jako počáteční argument. Další argumenty budeme předávat jako obvykle uvnitř závorek. Tyto argumenty mohou být nějaké jiné textové řetězce nebo něco jiného.
Řetězcových metod je celá řada. Tyto metody můžeme klasifikovat dle účelu, který splňují:
- spojování a rozdělování
- ořezávání
- vyhledávání
- nahrazování
- zjišťovací metody
- formátování
Některé z nich dále probereme podrobně a ukážeme základní příklady jejich použití. Ostatní detaily o metodách třídy str
jsou k dispozici v dokumentaci https://docs.python.org/3/library/stdtypes.html#string-methods.
Spojování a rozdělování stringů¶
Spojování dvou stringů můžeme udělat pomocí operátoru +
. Pokud chceme zřetězit více stringů, anebo dělat zřetězení v cyklu, výpočet se může kvůli neustálému vytváření nových instancí a kopírování předešlých výrazně zpomalit. V takovém případě je možné použít metodu join(iterable)
. Tato metoda očekává v argumentu iterable
zdroj stringů, které sloučí, přičemž mezi ně vloží vždy obsah objektu, který ji volá. Pak ten zřetězený string vrátí jako svoji návratovou hodnotu.
ovoce = ["Jablko", "Hruška", "Meruňka"]
s1 = ", ".join(ovoce) # Jako oddělovač používáme čárku s mezerou
s2 = "".join(ovoce) # Prázdný řetězec znamená, že bude to zřetězování bez oddělovače
s3 = "; ".join("Jablko") # Tady máme jako argument jen jeden string, Python ho považuje za tzv. generátor jednoznakových stringů
print(s1)
print(s2)
print(s3)
Jablko, Hruška, Meruňka JablkoHruškaMeruňka J; a; b; l; k; o
Stejně jako umíme stringy spojovat, občas je potřeba celý string rozložit na jednotlivé části. Tuto funkcionalitu nabízejí metody split()
, rsplit()
, partition()
, rpartition()
, splitlines()
.
Metoda split(sep=None, maxsplit=-1)
má dva parametry, oba mají výchozí hodnotu. sep
slouží k určeni podřetězce, který bude vystupovat jako oddělovač neboli separátor. Když nezadáme při volání první argument nebo bude None
, jako separátor vystupují jeden či více sousedících bílých znaků. Jinak narazíme-li na dva sousední oddělovače, nesloučíme je v jeden, ale dostaneme na příslušném místě prázdný řetězec. Hodnota maxsplit
určuje, maximálně kolikrát se daný separátor při rozdělování použije. Je-li v stringu nalezen vícekrát, další výskyty se ignorují. Výsledkem volání metody split()
je seznam stringů, přičemž každý je částí původního stringu v odpovídajícím pořadí. Metoda rsplit()
má stejné parametry a nabízí stejnou funkcionalitu, jen prohledává řetězec od konce.
list1 = "Jablko a hruška a meruňka".split(" a ")
list2 = "Jablko,,hruška,,meruňka".split(",") # Separátory se neslučují
list3 = "Jablko a hruška\na meruňka".split() # Používají se výchozí hodnoty parametrů
list4 = "Jablko,,hruška,,meruňka".split(";") # Separátor není nalezen
list5 = "Jablko a hruška a meruňka".split(" a ", 1) # Určujeme maximální počet použití separátoru
list6 = "Jablko a hruška a meruňka".rsplit(" a ", 1) # Začínáme zprava
print(list1, list2, list3, list4, list5, list6, sep="\n")
['Jablko', 'a', 'hruška', 'a', 'meruňka'] ['Jablko', '', 'hruška', '', 'meruňka'] ['Jablko', 'a', 'hruška', 'a', 'meruňka'] ['Jablko,,hruška,,meruňka'] ['Jablko', 'hruška a meruňka'] ['Jablko a hruška', 'meruňka']
Metody partition()
a rpartition()
se používají k podobnému učelu. Na rozdíl od metod split()
a rsplit()
, nevracejí seznam oddělených částí, ale n-tici (začátek, separátor, konec). Mají v závorce jen jeden parametr sep
, a ten výchozí hodnotu nemá.
ntice1 = "Jablko a hruška a meruňka".partition(" a ")
ntice2 = "ZPRO_Cv13.ipynb".partition(".")
ntice3 = "Jablko a hruška a meruňka".partition(",") # Separátor není nalezen
ntice4 = "Jablko a hruška a meruňka".rpartition(" a ") # Hledáme separátor zprava
print(ntice1, ntice2, ntice3, ntice4, sep="\n")
ntice5 = "Jablko a hruška a meruňka".partition() # TypeError: použití bez určení separátoru není povoleno
('Jablko', ' a ', 'hruška a meruňka') ('ZPRO_Cv13', '.', 'ipynb') ('Jablko a hruška a meruňka', '', '') ('Jablko a hruška', ' a ', 'meruňka')
--------------------------------------------------------------------------- TypeError Traceback (most recent call last) Cell In[26], line 6 4 ntice4 = "Jablko a hruška a meruňka".rpartition(" a ") # Hledáme separátor zprava 5 print(ntice1, ntice2, ntice3, ntice4, sep="\n") ----> 6 ntice5 = "Jablko a hruška a meruňka".partition() # TypeError: použití bez určení separátoru není povoleno TypeError: str.partition() takes exactly one argument (0 given)
Když chceme víceřádkový text rozdělit na jednotlivé řádky, je vhodné použití metody splitlines(keepends=False)
, která vrácí seznam stringů jednotlivých řádků. Standardně stringy ve vraceném seznamu nebudou obsahovat znaky ukončení řádku. Můžeme ale o tom požádat s hodnotou nepovinného pojmenovaného parametru jako True
.
Pro chytřejší rozdělování stringů se budou používat regulární výrazy.
Ořezávání stringů¶
Často potřebujeme vstup od uživatele zkontrolovat, případně hned opravit. Jednou z běžných nepřesností na webu a v textech jsou zbytečné mezery na začátku či konci řetězce. Toto může vyprovokovat např. chyby v uložení dat, jejich vyhledávání a uspořádání. "Vyčistit" takové chyby v Pythonu nám pomůžou metody lstrip()
, rstrip()
a strip()
, které odstraňují bílé znaky resp. ze začátku, z konce nebo ze začátku i konce stringu. Všechny bílé znaky uprostřed textu zůstanou.
Všechny tři uvedené metody jsou ale univerzálnější. Zavoláme-li je se zadaným argumentem, očekávají v něm string s množinou znaků, které mají na počátku a/nebo na konci stringu odebrat. Případné výskyty těchto znaků uvnitř textu samozřejmě zůstanou.
s1 = " Nechci bílé znaky před ani za textem! \n ".strip()
s2 = " Nechci bílé znaky před textem! \n ".lstrip()
s3 = " Nechci bílé znaky za textem! \n ".rstrip()
s4 = "* Nechci * před ani za textem!****".strip("* ")
s5 = "*--Nechci * ani - za textem!**---".rstrip("*-")
print(s1, s2, s3, s4, s5, sep="\n")
Nechci bílé znaky před ani za textem! Nechci bílé znaky před textem! Nechci bílé znaky za textem! Nechci * před ani za textem! *--Nechci * ani - za textem!
V Pythonu také jsou metody removeprefix()
a removesuffix()
, které umějí odstranit zadanou předponu resp. příponu v našem stringu. Podrobnosti o nich snadno najděte v dokumentaci.
Vyhledávání podstringů¶
Teď se budeme zabývat vyhledáváním zadaného podstringů. Tomu účelu v Pythonu slouží celá sada metod. Všechny tyto metody kromě vlastně hledaného podstringu mají implicitní parametry start
a end
definující podstring nebo slice [stard:end]
(to znamená od pozice start
do pozice end
a tu už ne) původního stringu, v němž se vykonává vyhledávání. Parametry start
a end
jsou poziční nikoliv pojmenované, proto potřebujete-li zadat konec prohledávaného slicu, musíte zadat i počáteční.
Metody | Krátký popis |
---|---|
count() |
Vrací počet nepřekrývajících se výskytů zadaného podstringu. |
find() , rfind() |
Vracejí pozici počátku prvního výskytu zadaného podstringu. Není-li podstring nalezen, vrátí -1 . Metoda rfind() prohledává zprava. |
index() , rindex() |
Pracují stejně jako metody find() , resp. rfind() . Liší se pouze tím, že nenajdou-li hledaný řetězec, vyvolají výjimku ValueError . |
startswith() , endswith() |
Vracejí True v případě, začíná-li (resp. končí-li) prohledávaný řetězec zadaným stringem. Prvním argumentem může vystupovat i n-tice stringů. |
Příklady použití těchto metod budou dost jednoduché, můžete je zkusit vymyslet samostatně.
# Write your exercise code here
print("a mamama mama".count("mam"))
print("a mamama mama".find("mam"))
print("a mamama mama".rfind("mam"))
print("a mamama mama".find("ham"))
print("a mamama mama".rfind("ham"))
print("a mamama mama".startswith("a "))
2 2 9 -1 -1 True
Metody nahrazování¶
Relativně často potřebujeme nejen zkontrolovat, obsahuje-li řetězec zadaný podstring, ale i nahradit ho nějakým jiným textem. V nejjednodušším případě stačí k tomu použit metodu replace(old:str, new:str, count:int=0)
. Jako první parametr metoda očekává hledaný nahrazovaný text, jako druhý text, který jej má nahradit, a ve třetím nepovinném maximálně povolený počet nahrazení. Nezadáme-li třetí parametr, nahradí se všechny výskyty.
s1 = "Ve slově standart se na konci nepíše t, ale d!"
print(s1.replace("t", "d"))
print(s1.replace("t", "d", 2))
print(s1)
s = "a mamama mama"
print(s.replace("a","A"))
print(s.replace("am","*"))
print(s.replace("a",""))
print(s.replace("a","A",3))
Ve slově sdandard se na konci nepíše d, ale d! Ve slově sdandard se na konci nepíše t, ale d! Ve slově standart se na konci nepíše t, ale d! A mAmAmA mAmA a m**a m*a mmm mm A mAmAma mama
Zmiňme ještě jednu nahrazovací metodu expandtabs(tabsize=8)
, která vrací kopii osloveného stringu, v níž jsou tabulátory nahrazeny sadou mezer tak, aby to odpovídalo zadané velikosti kroku tabulátoru. Krok tabulátoru můžeme ukázat jako argument, defaultní hodnotou je 8 znaků.
print("01\t012\t0123\t01234".expandtabs())
print("01\t012\t0123\t01234".expandtabs(4))
01 012 0123 01234 01 012 0123 01234
Pro zajímavější případy nahrazování často je vhodné využít možností regulárních výrazů.
Zjišťovací metody¶
Třída str
nabízí množinu bezparametrických metod vracejících hodnotu logického typu, která nás informuje o některých celkových vlastnostech textového řetězce. Příklady použití těchto metod zůstanou k samostatnému procvičení.
Metoda | Krátký popis |
---|---|
islower() |
Vrací True , je-li ve stringu alespoň jedno písmeno a všechna písmena jsou malá. Znaky, které nejsou písmeny, výsledek neovlivní. |
isupper() |
Vrací True , je-li ve stringu alespoň jedno písmeno a všechna písmena jsou velká. Znaky, které nejsou písmeny, výsledek neovlivní. |
istitle() |
Vrací True , je-li ve stringu alespoň jedno písmeno a mají-li ve stringu všechna slova první písmeno velké a ostatní malá. Znaky, které nejsou písmeny, výsledek neovlivní. |
isalpha() |
Vrací True , je-li string neprázdný a všechny jeho znaky jsou v sadě Unicode považovány za písmena. |
isnumeric() |
Vrací True , je-li string neprázdný a všechny jeho znaky jsou v sadě Unicode považovány za reprezentanty čísel. Sem patří vedle číslic i řada dalších znaků reprezentujících některé zlomky, římské číslice a jiné. |
isdigit() |
Vrací True , je-li string neprázdný a všechny jeho znaky jsou v sadě Unicode považovány za číslice. Vedle běžných číslic a číslic zapsaných jako indexy či exponenty sem patří i číslice dalších jazyků – např. arabsko-indické. |
isdecimal() |
Vrací True , je-li string neprázdný a všechny jeho znaky mohou být použity pro zápis čísel o základu 10. |
isalnum() |
Vrací True , je-li string neprázdný a všechny znaky představují písmena, číslice či čísla. Za alfanumerický je znak c považován v případě, vrací-li True alespoň jedna z metod c.isalpha() , c.isdecimal() , c.isdigit() , c.isnumeric() . |
isspace() |
Vrací True , je-li string neprázdný a všechny jeho znaky jsou v sadě Unicode klasifikovány jako bílé znaky. |
isprintable() |
Vrací True , je-li string prázdný, nebo obsahuje pouze tisknutelné znaky. Za netisknutelné znaky jsou mimo jiné považovány všechny bílé znaky s výjimkou obyčejné mezery (pevná mezera '\xA0' je proto netisknutelný znak). |
isascii() |
Vrací True , je-li string prázdný, nebo mají všechny jeho znaky kód menší nebo roven 255 (0x7F ). |
isidentifier() |
Vrací True , je-li string platným identifikátorem podle pravidel Pythonu. |
# Write your exercise code here
print("ahoj".islower()) # True
print("ahoj lidi_;\t\"".islower()) # True
print("ahojA".islower(), "\n") # False
print("AHOJ!!! ".isupper()) # True
print("ahOj".isalpha()) # True
print("ahoOj ".isalpha(), "\n") # False
print("23".isnumeric()) # True
print("2.3".isnumeric()) # False
print("2_3".isnumeric()) # False
print("-23".isnumeric()) # False
True True False True True False True False False False
Metody pro jednoduché formátování¶
Pro jednoduché formátování, které se tyká změny velikosti písmen, Python nabízí několik snadných bezparametrických metod. Znaky, které se nepovažují za písmena, použití těchto metod neovlivní.
Metoda | Krátký popis |
---|---|
lower() |
Vrátí nový string vzniklý převodem svého stringu na malá písmena. |
upper() |
Vrátí nový string vzniklý převodem svého stringu na velká písmena. |
capitalize() |
Vrátí nový string vzniklý převodem svého stringu na malá písmena s výjimkou prvního znaku, který bude velký. |
title() |
Vrátí nový string vzniklý převodem svého stringu na malá písmena s prvními znaky všech slov velkými písmeny. Používá se jednoduchá jazykonezávislá definice slova jako skupiny po sobě jdoucích písmen. Tato definice funguje v mnoha kontextech, ale znamená to, že např. apostrofy mohou mít nepožadovaný vliv na výsledek. |
s1 = "Text z malých písmen, VELKÝCH PÍSMEN a čísla 42."
print(s1.lower(), s1.upper(), s1.capitalize(), s1.title(), sep="\n")
s2 = "they're bill's friends from the UK"
print(s2.title())
text z malých písmen, velkých písmen a čísla 42. TEXT Z MALÝCH PÍSMEN, VELKÝCH PÍSMEN A ČÍSLA 42. Text z malých písmen, velkých písmen a čísla 42. Text Z Malých Písmen, Velkých Písmen A Čísla 42. They'Re Bill'S Friends From The Uk
Aby velké texty vypadaly čitelněji, může se objevit potřeba udělat zarovnávání doleva, doprava, nebo na střed. Pomohou v tom metody ljust()
, rjust()
a center()
resp. Povinným pozičním parametrem všech těchto metod je požadovaná délka výstupního stringu. Zadaný text bude podle typu zarovnání standardně doplněn mezerami na konci a/nebo na začátku na požadovanou délku. V druhém nepovinném parametru můžeme určit, jaký znak se má použít k doplnění stringu místo standardní mezery.
print("|", "vlevo".ljust(20), "|", "uprostřed".center(20), "|", "vpravo".rjust(20), "|")
print ("Ahoj!".center(40, '.'))
| vlevo | uprostřed | vpravo | .................Ahoj!..................
Formátovací řetězce a metoda format()
¶
Zatím v případě, když jsme chtěli udělat nějaký pochopitelný výstup pro uživatele (např. nejen vypsat nějaké číslo ale doplnit výsledek krátkým vysvětlením), byli jsme nuceni používat ve funkci print()
"mix" hodnot a výrazů.
hodiny = 2
minuty = hodiny * 60
print(hodiny, "hod je", minuty, "min")
2 hod je 120 min
Pro velké výstupy již to nebude tak snadno. A kromě toho někdy potřebujeme ten celý výstupní string uložit. Zřejmě můžeme vytvořit řetězec pomocí zřetězování. Python ale nabízí elegantnější způsob takového formátování.
Znázorníme to jako textovou šablonu s nějakými prázdnými místy, které potom chceme vyplnit konkrétními hodnotami.
Mil[ý/á] _______,
Váš výsledek 1. testu ZPRO je __________ bodů.
S pozdravem
_________
Aby Python věděl, do kterého vynechaného místa co doplnit, je potřeba jednotlivá vynechaná místa ve formuláři nějak jednoznačně označit. K tomu se používají složené závorky a identifikátory.
Mil{y_a} {osloveni},
Váš výsledek 1. testu ZPRO je {soucet} bodů.
S pozdravem,
{podpis}.
Takovou textovou šablonu můžeme použít jako tzv. formátovací řetězec nebo f-string (anglicky formatted string literal). Formátovací řetězec se vytvořuje stejně jako obyčejný řetězec, jen aby bylo jasné, že nejde o "standardní" string ale f-string, před první uvozovky musíme přidat předponu f
nebo F
.
Pák pro uvedenou situaci můžeme vytvořit jednoduchý programní "skript":
y_a = "á"
osloveni = "Žofie"
ukol1 = 25
ukol2 = 40
ukol3 = 20
soucet = ukol1 + ukol2 + ukol3
podpis = "Já"
vystup = f"""
Mil{y_a} {osloveni},
Váš výsledek 1. testu ZPRO je {soucet} bodů.
S pozdravem,
{podpis}
"""
print(vystup)
x = fr"\"ahoj"
print(x)
Milá Žofie, Váš výsledek 1. testu ZPRO je 85 bodů. S pozdravem, Já \"ahoj
Místo identifikátorů proměnných v složených závorkách vždy je možné použít jakékoli výrazy, volání funkcí apod.
V literatuře se práce s f-stringy často označuje jako literálová stringová interpolace (anglicky Literal String Interpolation). To znamená, že f-stringový literál nedefinuje ten textový řetězec přesně, ale obsahuje různé interpolace, jejichž vyhodnocením získáme konečný tvar.
Shrneme tedy základy pro práci s f-stringy, které nám ukážou i některé další možnosti:
- Pro f-stringy platí stejná pravidla jako pro obyčejné textové řetězce. Mohou je ohraničovat jednoduché, dvojité uvozovky nebo jejich trojice. Liší se pouze tím, že před úvodním ohraničením píšeme předponu
f
neboF
. - F-stringy mohou obsahovat nahrazovací pole, v nichž se mohou vyskytovat výrazy, jejichž hodnota se má zobrazit.
- Výrazy v nahrazovacích polích jsou vyhodnocovány zleva doprava, což má vliv na výsledek pouze tehdy, budou-li mít některé vyhodnocované výrazy vedlejší efekt.
- F-stringy můžeme vytvořit jako součet nebo složeni několika stringů, avšak musíme dát pozor, aby všechny sčítance obsahující nahrazovací pole byly zadány jako f-stringy, protože jinak se v součtu uplatní pouze jako obyčejný string.
- Při ladění můžeme využít toho, že bude-li výraz v složených uvozovkách končit rovnítkem, bude vypsán celý ten výraz včetně případných mezer a závěrečného rovnítka, a za něj pak výsledek interpolace.
- Předponu
f
/F
lze doplnit i předponour
/R
, která určuje tzv. surový literál.
Poznámka: Surový (ve smyslu nezpracovaný) literál (anglicky raw literal) nerespektuje escape sekvence, každý znak v něm představuje sám sebe. Výjimkou jsou pouze uvozovky, je musíme nadále zadávat se zpětným lomítkem. Surový stringový literál se výhodně používá při zadávání cest k souborům nebo regulárních výrazů.
print(f"abcd \\\tvgh")
print(fr"abcd \\\tvgh")
abcd \ vgh abcd \\\tvgh
Někdy se může stát, že jednu textovou šablonu chceme použít několikrát. V tom nám f-string již tak snadno nepomůže, protože se do něj "prázdná místa" doplňují automaticky a hned. V takovém případě je možné použit metodu format()
pro obyčejný string.
Poznámka:
Pravda je v tom, že f-stringy je novější možnost Pythonu, která byla zavedena až ve verzi 3.6. Metoda format()
se objevila dřív spolu s Python 3. Pravidla pro formátování nahrazovacích polí v f-strinzích jsou fakticky převzatá z metody format()
.
Hlavička metody format()
má tvar format(*args, **kwds)
, což znamená, že její argumenty můžeme odvolávat jak jejich pořadím, tak i jejich názvem. To dává výhodu oproti formátovacím řetězcům. Nejsme povinní dosazované hodnoty vždy jmenovat: nepojmenované argumenty se dosadí postupně do nepojmenovaných míst v textové šabloně.
s1 = "{} krát {} je {}.".format(2, 2, 2 * 2)
print(s1)
s2 = "Ahoj, jsem {jmeno}. A moje oblibené číslo je {cislo}."
print(s2.format(cislo=7, jmeno="Matěj"))
print(s2.format(cislo=42, jmeno="divný člověk"))
print(s2.format(jmeno="Žofie", cislo=3)) # KeyError: není možné dosadit nepojmenovaný argument do pojmenovaného místa
2 krát 2 je 4. Ahoj, jsem Matěj. A moje oblibené číslo je 7. Ahoj, jsem divný člověk. A moje oblibené číslo je 42. Ahoj, jsem Žofie. A moje oblibené číslo je 3.
Příklady¶
- Silné heslo. Heslo budeme označovat jako silné, jsou-li splněná následující kritéria:
- Heslo obsahuje malá písmena latinské abecedy.
- Heslo obsahuje velká písmena latinské abecedy.
- Heslo obsahuje číslice.
- Heslo obsahuje alespoň jeden ze znaků
! " # $ % & ' ( ) * +
. - Délka hesla není menší než 8 znaků.
Napište funkci, která zjistí (a ve vhodné formě vrátí), které z těchto pěti kritérií silného hesla jsou pro použité heslo splněny.
def strong_password(passwd):
a = b = c = d = e = False
for x in passwd:
if x.islower():
a = True
if x.isupper():
b = True
if x.isnumeric():
c = True
if x in "!\"#$%&'()*+":
d = True
if len(passwd)>=8:
e = True
return a, b, c, d, e
print(strong_password("Moje8Heslo'")) # splňuje všechna kriteria
(True, True, True, True, True)
- Anagramy. Slovo je anagramem jiného slova, když ho lze získat přeuspořádáním jeho písmen. Napište funkci
anagrams(word1, word2)
, která vrátíTrue
, pokud jsou tato dvě slova anagramy, aFalse
, pokud nejsou.
str = "abcdabcdda"
l = sorted(str)
print(l)
['a', 'a', 'a', 'b', 'b', 'c', 'c', 'd', 'd', 'd']
def anagrams(str1, str2):
return sorted(str1) == sorted(str2)
assert anagrams("reklama", "makrela")
assert anagrams("reklama", "marekll") == False
assert anagrams("reklama", "mareklla") == False
assert anagrams("reklama", "marek") == False
assert anagrams("reklama", "mareklaa") == False
def anagrams(str1, str2):
for x in set(str1): # for x in str1:
if str1.count(x) != str2.count(x):
return False
return True
assert anagrams("reklama", "makrela")
assert anagrams("reklama", "marekll") == False
assert anagrams("reklama", "mareklla") == False
assert anagrams("reklama", "marek") == False
assert anagrams("reklama", "mareklaa") == False
def anagrams(str1, str2):
for x in str1:
if x not in str2:
return False
else:
str2 = str2.replace(x,"",1)
return len(str2)==0
assert anagrams("reklama", "makrela")
assert anagrams("reklama", "marekll") == False
assert anagrams("reklama", "mareklla") == False
assert anagrams("reklama", "marek") == False
assert anagrams("reklama", "mareklaa") == False
- Iniciály. Napište program, který se zeptá uživatele na jméno, pak na příjmení a potom vypíše iniciály – první písmena zadaných jmen. Iniciály jsou vždy velkými písmeny (i kdyby byl uživatel líný mačkat
Shift
). Možné náhodné mezery na začátku jména nebo příjmení také odstraňte. Pro převod zadaných jmén na iniciály použijte pomocnou funkciget_initials(name, surname)
.
def get_initials(name, surname):
name = name.lstrip()
surname = surname.lstrip()
# Získáme první písmeno ze jména
initials = name[0] + surname[0]
# Převedeme iniciály na velká písmena
return initials.upper()
assert get_initials(" jan ", " novák") == "JN"
x = input("Zadej jméno:")
y = input("Zadej příjmení:")
v = get_initials(x,y)
print(f"tvé iniciály jsou {v}.")
tvé iniciály jsou AF.
- Frekvenční analýza. Napište funkci
freq_analysis(text)
, která spočítá výskyt jednotlivých písmen (znaků) ve vstupním textu a vrátí výsledek jako slovník nebo jako seznam dvojic (znak, počet výskytů). Vypište znaky s počty jejich výskytů setříděné sestupně podle počtu výskytů.
def freq_analysis(text):
dict = {}
text = text.lower()
for c in set(text):
if c.isalnum():
dict[c]=text.count(c)
return dict
d = freq_analysis("All the world is a stage and all the men and women merely players.")
print(d)
#v = sorted(d.items(), key=lambda x: x[1], reverse=True)
{'l': 7, 'r': 3, 'm': 3, 't': 3, 'a': 7, 'e': 8, 'g': 1, 'n': 4, 'p': 1, 'd': 3, 'h': 2, 's': 3, 'y': 2, 'i': 1, 'w': 2, 'o': 2}
def freq_analysis(text):
dict = {}
text = text.lower()
for c in text:
if c.isalnum():
if c in dict:
dict[c]+=1
else:
dict[c] = 1
return dict
d = freq_analysis("All the world is a stage and all the men and women merely players.")
print(d)
#v = sorted(d.items(), key=lambda x: x[1], reverse=True)
{'a': 7, 'l': 7, 't': 3, 'h': 2, 'e': 8, 'w': 2, 'o': 2, 'r': 3, 'd': 3, 'i': 1, 's': 3, 'g': 1, 'n': 4, 'm': 3, 'y': 2, 'p': 1}
- Délka slov. Naprogramujte funkci, která zjistí délku každého slova v textu. Předpokládejme, že slova jsou oddělená pomocí obyčejných mezer (možná několika za sebou).
def word_lengths(text):
words = text.split()
word_lengths = []
for word in words:
word = word.strip(".,!?()[]{}'\"")
word_lengths.append(len(word))
return word_lengths
text = "Toto je příklad textu s různě dlouhými slovy."
print(word_lengths(text))
assert word_lengths(" Toto je příklad textu s různě dlouhými slovy. ") == [4, 2, 7, 5, 1, 5, 8, 5]
[4, 2, 7, 5, 1, 5, 8, 5]
- Frekvenční analýza slov. Napište funkci
freq_analysis(text)
, která spočítá výskytů jednotlivých slov ve vstupním textu a vrátí výsledek jako slovník nebo jako seznam dvojic (slovo, počet výskytů). Vypište slova s počty jejich výskytů setříděné vzestupně podle abecedy.
def freq_analysis(text):
text = text.lower()
words = text.split()
for i in range(len(words)):
words[i] = words[i].strip(".,!?()[]{}'\"")
d = {}
for word in words:
if word in d:
d[word] += 1
else:
d[word] = 1
return d
d = freq_analysis("This is a test. This is only a test, not a real situation.")
print(d)
d_sorted = dict(sorted(d.items()))
print(d_sorted)
{'this': 2, 'is': 2, 'a': 3, 'test': 2, 'only': 1, 'not': 1, 'real': 1, 'situation': 1} {'a': 3, 'is': 2, 'not': 1, 'only': 1, 'real': 1, 'situation': 1, 'test': 2, 'this': 2}
- Caesarova šifra. Vytvořte si funkci, která zrealizuje šifrování algoritmem Caesarové šifry. To šifrování spočívá v posouvání každého písmena řetězce o určitý počet znaků dle abecedy. Například slovo
"Ahoj"
se s posunem 1 převede na"Bipk"
. Ten posun – klič šifry – povolte vybrat uživateli. Jak by se naprogramovala funkce pro dešifrování?
def caesar(text, shift):
...
a = "abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ"
assert caesar(a,12) == "mnopqrstuvwxyzabcdefghijkl MNOPQRSTUVWXYZABCDEFGHIJKL"
b = "All the world is a stage; And all the men and women merely players."
assert caesar(b, -2) == "Yjj rfc umpjb gq y qryec; Ylb yjj rfc kcl ylb umkcl kcpcjw njywcpq."
assert caesar(b, 26) == b
assert caesar(caesar(b,15), -15) == b
- Kryptoanalýza Caesarovy šifry. Caesarovu šifru lze velmi lehko vyluštit (tj. zjistit neznámý posun – tajný klíč). Zkuste naprogramovat dvě funkce, první implementuje tzv. metodu hrubé sily, druhá způsob frekvenční analýzy.
print(caesar("Ask me, how to "))
def try_caesar(text):
...
try_caesar("Clguba vf n irel hfrshy cebtenzzvat ynathntr. Naq ubj fvzcyr vg vf... V ybir vg!")
def caesar_frequency_analysis(text):
...
caesar_frequency_analysis("Clguba vf n irel hfrshy cebtenzzvat ynathntr. Naq ubj fvzcyr vg vf... V ybir vg!")