Řetězce (strings) jsou neměnitelné sekvence znaků Unicode, vymezené uvozovkami - jednoduchými, dvojitými či trojitými.
Výraz
Pořadí znaku v řetězci je interně indexováno zleva i zprava, neboli je vyjádřeno pořadovým číslem, které zleva začíná nulou - viz kap. 3.2.
Vymezená část řetězce se nazývá úsek (slice). Výběr úseku se provádí úsekovým operátorem nebo funkcí slice() - viz kap. 3.3.
Délku řetězce určíme funkcí
>>> fruit = "banana" >>> len(fruit) 6
Ve snaze získat poslední písmeno řetězce bychom mohli být v pokušení zkusit něco jako:
>>> délka = len(fruit) >>> last = fruit[délka]IndexError: string index out of range >>> last = fruit[délka-1] a
Obecně vzato, na řetězcích nelze provádět matematické operace. Následující výrazy nejsou přípustné :
"uno" - 1 "Hello / 123 "duo" * "Hello" "15" + 2
Operátor
>>> "Chléb " + " a hry"# spojení dvou řetězců Chléb a hry >>> 1, 2, 3, + 4, 5, 6# oba operandy jsou entice (1, 2, 3, 4, 5, 6) >>> 1, 2, 3 + 4, 5, 6# jde o jednu entici s vloženým součtem 3+4 (1, 2, 7, 5, 6) >>> [1, 2, 3] + [4, 5, 6]# spojení dvou seznamů [1, 2, 3, 4, 5, 6]
Řetězce jsou neměnitelné, což znamená, že existující řetězec nelze změnit. Jediná věc, kterou lze udělat, je vytvořit nový řetězec, který je variací původního:
greeting = "Hello, world!" new_greeting = greeting[:5]+ " all"+ greeting[6:]
Řešením je zřetězení vložené části s úseky řetězce
Operátor násobení
>>> 3 * "bla " == "bla " * 3 == "bla bla bla " True >>> (1, 2, 3) * 3# zde entice jen v závorkách! (1, 2, 3, 1, 2, 3, 1, 2, 3) >>> [1, 2, 3] * 3 [1, 2, 3, 1, 2, 3, 1, 2, 3]
Kromě společných procedur pro řetězce a seznamy existuje také velké množství
capitalize, casefold, center, count, encode, endswith, expandtabs, find, format, format_map, index, isalnum, isalpha, isdecimal, isdigit, isidentifier, islower, isnumeric, isprintable, isspace, istitle, isupper, join, ljust, lower, lstrip, maketrans, partition, replace, rfind, rindex, rjust, rpartition, rsplit, rstrip, split, splitlines, startswith, strip, swapcase, title, translate, upper, zfill
Například:
>>> he = "Hurvínek" >>> he.upper() 'HURVÍNEK'
Z řetězce umíme vytvořit seznam (
>>> str (list("Žabička")) "['Ž', 'a', 'b', 'i', 'č', 'k', 'a']"
Metoda
'separ'.join (iteráble)# 'separ' je vkládaný separátor
Chceme-li z rozsypaného čaje sestavit zase žabičku, použijeme metodu
>>> frog = list("Žabička"); frog ['Ž', 'a', 'b', 'i', 'č', 'k', 'a'] >>> "".join(frog)# "" je formálně povinný argument 'Žabička'# bez něj by nešlo volat metodu >>> gong = "Kravička" >>> " * ".join(gong) 'K * r * a * v * i * č * k * a'
Metoda
Metoda
string.split (separátor, počet jeho použití)
Atributy metody
Nenachází-li se zadaný separátor či mezera v zadaném řetězci, řetězec se nerozdělí, pouze se vloží do listu.
>>> song = "Tam za vodou v rákosí ..." >>> song.split(" ",2)Zajímavé případy:# separátor, počet použití ['Tam', 'za', 'vodou v rákosí ...'] >>> song.split()# implicitní separace ['Tam', 'za', 'vodou', 'v', 'rákosí', '...'] >>> song.split(':')# dvojtečka v řetězci není ['Tam za vodou v rákosí ...']
>>> stig = "one,two,three" >>> stig.split(",")# symetrické umístění separátoru ['one', 'two', 'three']# OK, něma problema >>> stig.split(", ")# asymetrické umístění separátoru ['one,two,three']# Well, stig se jen vloží do listu >>> swig = 'a b \nc d \r\ne' >>> my_str.split() >>> swig.split("\nc") ['a b ', ' d \r\ne']
Vřele doporučuji otevřít si editor/shell
Modul
>>> import string
Obsah modulu zjistíme vestavěnou fcí
>>> dir(string)
čímž dostaneme seznam specielních metod:
['Formatter', 'Template', '_ChainMap', '__all__', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '_re', '__spec__', '_sentinel_dict', '_string', ...
a atributů:
... 'ascii_letters', ascii_lowercase', 'ascii_uppercase' 'capwords', digits', hexdigits', 'octdigits', printable', punctuation', 'whitespace']
Udělejte si průzkum a sami si zjistěte, co jednotlivé atributy vracejí:
>>> string.digits '0123456789' >>> string.punctuation '!"#$%&\'()*+,-./:<=>?@[\\]^_`{|}~' >>> string.whitespace '\t\n\r\x0b\x0c'escape sekvence pro whitespace
Znaky whitespace posouvají kurzor, aniž by se cokoli tisklo. Vytvářejí prázdné místo mezi viditelnými znaky.
Konstanty lze s výhodou použít v různých ověřovacích funkcích, například:
def is_lower (ch):return string.ascii_lowercase.find(ch) != -1
Nutno si uvědomit, že tato funkce neodpovídá na otázku, zda zkoumané písmeno je velké či malé ale zda patří do sady
>>> is_lower("ch") False
Metoda
>>> string.capwords("Honolulu ", "o") 'HoNoLulu ' >>> string.capwords(" Hono Lu lU", "čau") ' hono lu lu' >>> string.capwords(" Honolulu ") 'Honolulu'
Operátor příslušnosti
>>> 'p' in 'apple' True >>> 'i' in 'apple' False >>> 'ap' not in 'apple' False >>> 'pa' not in 'apple' TrueVšimněme si, že řetězec může být součástí sebe sama:
>>> 'a' in 'a' True >>> 'apple' in 'apple' True
Použitím operátoru
def remove_vowels (str): samohl = "aeiouyAEIOUY" str_bez_samohl = ""# akumulátor for letterin str:if letternot in samohl: str_bez_samohl += letterreturn str_bez_samohl
>>> remove_vowels("akumulátor") 'kmlátr'
Prázdný objekt, označený jako akumulátor, je kontejner (zde řetězec) s rozšiřujícím se obsahem.
Podobným objektem je počítadlo, kde se mění jen počáteční stav čísla.
Při porovnávání řetězců se postupně porovnávají kódová čísla znaků se stejným indexem. Postupuje se zleva doprava.
Rovnost řetězců zjistíme:
word = "Zebra"if word== "banana":
Jiné relační operátory jsou užitečné při uspořádávání slov podle abecedy:
if word== "banana":+ word+ ", comes before banana.")elif word> "banana":+ word+ ", comes after banana.")else :
Musíme si však být vědomi toho, že Python řadí velká písmena (v důsledku svých číselných hodnot) před malá, proto:
Your word, Zebra, comes before banana.
Souvislost znaku s číselnou hodnotou nám také umožňuje použít funkce
>>> min("žoužel"), max("žoužel") ('e', 'ž') >>> ord(min("žoužel")), ord(max("žoužel")) (101, 382) >>> chr(101), chr(382) ('e', 'ž')
Řetězce jsou sice neměnitelné ale lze libovolně upravovat jejich (často interně vytvářené) kopie. Pro tento účel existuje řada funkcí a metod.
Těmito metodami lze změnit začátek a konec řetězce:
>>> "some Text".removeprefix("some ") 'Text' >>> "some Text".removesuffix("Text") 'some '
Metoda
>>> ring = "horo, horo, vysoká jsi" >>> (fing := ring.replace("horo", "Horo", 1)) 'Horo, horo, vysoká jsi'
Použitím metody
>>> abr = "abrakadabra" >>> abr.replace("a", "") 'brkdbr'
V případě potřeby si můžeme napsat proceduru (zde funkci) sami, například chceme-li zbavit řetězec předdefinované sady znaků, prezentované jako "punctuation".
K vlastnímu vyzkoušení použijte prostředí IDLE:
import stringdef remove_punct (s): s_without_punct = ""proměnná zvaná akumulátor for letterin s:if letternot in string.punctuation: s_without_punct += letterreturn s_without_punct str = "Až na severní pól, běží liška!"# Ctrl-S, F5 v IDLE: Až na severní pól běží liška
>>> import string as str >>> str.punctuation "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~"
Cvičení: Můžeme si definovat vlastní soubor znaků, napříkad"žšěíó" . Pro jeho použití upravte funkciremove_punct(s) .
Vrací index prvního výskytu zadaného substringu v prohledávaném řetězci. Schéma volání metody
string.find (sub [,start [, end]]) sub - hledaný substring start - začátek hledání; implicitně je 0 end - konec hledání; implicitně konec řetězce
Metoda
>>> tanec = "Dokolečka dokola" >>> tanec.find("leč") 4
Jako naše funkce i tato metoda přijímá nepovinný argument, který určuje index u kterého má začít:
>>> tanec.find("kol", 4) 12
Odlišně od naší funkce, druhý nepovinný parametr metody určuje index, kde má hledání skončit:
>>> tanec.find("la", 1, 15) -1# návratová hodnota v případě neúspěchu
V tomto případě skončí hledání nezdarem, protože se substring
Vestavěnou metodu
string.count (value [, start [, end]])
>>> "abrakadabra".count("a") 5 >>> "abrakadabra".count("ra") 2 >>> "Až na severní pól".count(" ") 3
Uživatelská funkce
def find (strng, ch): index = 0while index < len(strng):if strng[index] == ch:return index index += 1return -1
V této funkci se opět setkáváme s příkazem
Není-li znak v řetězci obsažen, potom program opustí smyčku normálně a vrátí -1.
Tento způsob výpočtu je někdy nazýván traverzování Heuréka, protože jakmile nalezneme co hledáme, můžeme zvolat „Heuréka” a skončit hledání.
Pro stanovení počátku pro hledání můžeme do funkce přidat třetí parametr:
def find1 (strng, ch, start): index = startwhile index < len(strng):if strng[index] == ch:return index index += 1return -1
Volání
Funkci si vylepšíme úpravou parametru
def find2 (strng, ch, start=0): index = startwhile index < len(strng):if strng[index] == ch:return index index += 1return -1
Výsledek volání
Přidáním dalšího volitelného parametru do fce
def find3 (strng, ch, start=0, step=1): index = startwhile 0 <= index < len(strng):if strng[index] == ch:return index index += stepreturn -1
Zadání hodnoty
Starší a v Pythonu 3.x stále použitelný způsob formátování řetězce je s použitím
Schema formátování řetězce vypadá takto:
"řetězec sespecifikacemi "% (hodnoty specifikací )
Část
Nejlépe si to ukážeme na několika příkladech:
>>> "Jmenuje se %s." % "Arthur" 'Jmenuje se Arthur.' >>> name = "Alenka" >>> age = 16 >>> "Jsem %s a je mi %d let." % (name, age) 'Jsem Alenka a je mi 16 let.' >>> n1, n2 = 4, 5# enticové přiřazení >>> "2**10 = %d a %d*%d = %f" % (2**10, n1, n2, n1*n2) '2**10 = 1024 a 4*5 = 20.000000' >>>
V prvním uvedeném příkladě je jediná konverzní specifikace
Ve druhém příkladě má
Ve třetím příkladě mají proměnné
V následující ukázce vidíme příkaz k tisku, ve kterém k formátování řetězce použijeme únikový znak
i = 1# záhlaví while i <= 10:
Tento program vytiskne tabulku různých mocnin čísel od 1 do 10. V uvedeném tvaru je rovnání výsledků do sloupců způsobené únikovým znakem tabelátoru
i i**2 i**3 i**5 i**10 i**20 1 1 1 1 1 1 2 4 8 32 1024 1048576 3 9 27 243 59049 3486784401 4 16 64 1024 1048576 1099511627776 5 25 125 3125 9765625 95367431640625 6 36 216 7776 60466176 3656158440062976 7 49 343 16807 282475249 79792266297612001 8 64 512 32768 1073741824 1152921504606846976 9 81 729 59049 3486784401 12157665459056928801 10 100 1000 100000 10000000000 100000000000000000000
Mohli bychom změnit šířku sloupce ale vidíme, že první sloupce již teď mají více místa než potřebují. Nejlepší bude určit šířku pro každý sloupec jednotlivě. Jak lze tušit, řešení poskytuje formátovaný řetězec :
Schema zápisů: ("řetězec se specifikacemi") % (hodoty specifikací) i = 1while i <= 10:
Běh této verze dává následující výstup:
i i**2 i**3 i**5 i**10 i**20 1 1 1 1 1 1 2 4 8 32 1024 1048576 3 9 27 243 59049 3486784401 4 16 64 1024 1048576 1099511627776 5 25 125 3125 9765625 95367431640625 6 36 216 7776 60466176 3656158440062976 7 49 343 16807 282475249 79792266297612001 8 64 512 32768 1073741824 1152921504606846976 9 81 729 59049 3486784401 12157665459056928801 10 100 1000 100000 10000000000 100000000000000000000
Pomlčka (
Novější způsob formátování výstupu je pomocí metody
"řetězec_s_{výměnnými_poli} " .format (hodnoty výměnných polí)
Výměnná pole jsou instrukce, uzavřené ve složených závorkách
Výměnná pole jsou trojího druhu:
{označení, konverze, :specifikace} argumentu
Označení argumentu
je buď číslo, nebo klíčové slovo. Číslo odkazuje na poziční argument, klíčové slovo na pojmenovaný argument metody
Více než slova řekne ukázka:
>>> "Od {} do {}" .format("rána", 22.00)# dtto: "Od {0} do {1}" 'Od rána do 22.00' >>> "Jmenuji se {osel}" .format(osel = "Pavel") 'Jmenuji se Pavel'
Konverze argumentu
způsobí změnu typu před formátováním. Používá se značení
Ukázka přiblíží způsob použití:
>>> "Harold je chytrý {!s}" .format("chlapeček") 'Harold je chytrý chlapeček' >>> "Harold je chytrý {!r}" .format("chlapeček") "Harold je chytrý 'chlapeček'" >>> "Harold je chytrý {!a}" .format("chlapeček") "Harold je chytrý 'chlape\\u010dek'"# ošetřené ne-ASCii
Specifikace argumentu
upřesňuje, jak má být hodnota prezentována, to jest určuje:
Ukázka přiblíží způsob použití:
# číslice ve specifikaci určuje délku textového pole >>> "{:<25}" .format("zarovnáno vlevo") 'zarovnáno vlevo ' >>> "{:>25}" .format("zarovnáno vpravo") ' zarovnáno vpravo' >>> "{:ˇ^25}" .format("hulín")zarovnáno na střed 'ˇˇˇˇˇˇˇˇˇˇhulínˇˇˇˇˇˇˇˇˇˇ'
Další zajímavé příklady namátkou:
>>> import math >>> print("Hodnota pí je asi {0:.3f}" .format(math.pi)) Hodnota pí je asi 3.142 >>> >>> telef = {"Jan":4127, "Dana":4098, "Ota":863678} >>> for name, phone in telef.items():# viz konec Kap. 4.3 print("{0:10} ==> {1:10d}" .format(name, phone)) ... Jan ==> 4127 Dana ==> 4098 Ota ==> 863678
Máme-li pojmenované argumenty uloženy ve slovníku, můžeme použít jeho
>>> postava = {'name': 'Petr Parléř', 'age': 67} >>> "Stavitel {name} se dožil {age} let." .format(** postava) 'Stavitel Petr Parléř se dožil 67 let.'
Další příklady lze nalézt v literatuře, například The Python Tutorial - Input and Output
Najde se tam také tento užitečný:
>>> for x in range(7,11): ... print("{0:2d} {1:3d} {2:4d}" .format(x, x*x, x*x*x)) ... 7 49 343 8 64 512 9 81 729 10 100 1000 >>>
Zjednodušený způsob formátování řetězců byl zaveden ve verzi Python 3.6. Označuje se jako formátovaný literál řetězce (formated string literal), stručně
Obdobně jako u předchozího způsobu může tento literál obsahovat výměnná pole, ohraničená složenými závorkami
V této ukázce předvedeme f-string s výrazem (který se nejprve vyhodnotí):
>>> f"3 + 8/2 je {3 + 8/2}" '3 plus 8/2 je 7.0'
V následující ukázce vidíme volání funkce a metody:
>>> name = "IDLE" >>> def to_lowercase(input): return input.lower() >>> f"{to_lowercase(name)} je zábavné."volání funkce 'idle je zábavné.' >>> f"{name.lower()} je zábavné."volání metody 'idle je zábavné.'
V další ukázce je odkaz na slovník:
>>> postava = {'name': 'Petr Parléř', 'age': 67} >>> f"Stavitel {postava['name']} se dožil {postava['age']} let." 'Stavitel Petr Parléř se dožil 67 let.'# konverzní flag !a pro ASCii - viz 6.11: >>> f"Stavitel{postava['name']!a}" "Stavitel'Petr Parl\\xe9\\u0159'"
Python 3.8 přináší rozšíření f-stringu o rovnítko za jménem, které způsobí následné vytištění předem přiřazené hodnoty:
>>> python = 3.8 >>> f"{python}"; f"{python= }" '3.8'# bez rovnítka 'python = 3.8'# s rovnítkem
Další možností je použití mrožího operátoru uvnitř f-stringu:
>>> import math >>> r = 2.4 >>> f"Tyč o průměru {(d:= 2 * r)} cm má obvod {math.pi * d:.2f} cm" 'Tyč o průměru 4.8 cm má obvod 15.08 cm'
Formátování výstupů hodnot typu
Hodnoty | Formát | Příklad použití | Výstup |
---|---|---|---|
mil = 1000**2 | {:,} | Comma separator: |
1,000,000 |
mld = 1000**3 | {:.2e} | Exponent notation: | 1.00e+09 |
flt = 2.71828 | {:.2f} | Format float: |
2.72 |
flt = 2.71828 | round() | |
2.72 |
0.35 | {:.2%} | Procenta: |
35.00% |
x,y = string, 9 | {x: | Dorovnání vlevo: |
******aha |
x,y = string, 9 | {x: |
Dorovnání vpravo: |
aha****** |
x,y = string, 9 | {x: |
Zarovnání na střed: |
***aha*** |
Pro poslední tři ukázky si můžeme pamatovat, že výraz ve složených závorkách má obecně tuto skladbu:
{ arg: fill align width }kde: arg upravovaná hodnota typu int, float, string fill doplňovaný znak (zde asterix) align dorovnání vlevo, vpravo, na střed (>, <, ^) width celková šířka zaplňovaného pole (počet míst)
Pro čísla i řetěce lze použít také tento formát, kde rovnítko za jménem proměnné způsobí následné vytištění předem přiřazené hodnoty (bez příkazu "print"):
>>> x = "aha" >>> f"{x= :*>7}"# formátování výstupu 'x = ****aha'# aha dorovnáno na 7 míst zleva
V následné ukázce se nejedná o mroží operátor, nýbrž o formátování
>>> x = 3; f"{x := 8}" ' 3'# řetězec o délce 8 (včetně čísla 3)
Úniková sekvence (escape sequence) je tvořena zpětným lomítkem (backslash) a následným jedním či více znaky.
Používá se pro vkládání jinak nepřípustných znaků do řetězce.
Kód | Význam |
---|---|
\', \" | Vloží apostrof |
\\ | Vloží zpětné lomítko |
\n | Přejde na nový řádek |
\r | Aktivuje 'carriage return' |
\t | Aktivuje tabulátor |
\b | Smaže znak před lomítkem |
\f | Aktivuje 'form feed' |
\ooo | Octal value |
\xhh | Hex value |
Příklad na použití únikové sekvence
>>> strg = 'a\tb\nA\tB' >>> print(strg) a b A B
Takzvaný
>>> strg = r'a\tb\nA\tB'# zpětné lomítko je běžný znak >>> print(strg) a\tb\nA\tB
Kromě jednoduchých a dvojitých uvozovek zná Python také řetězce s trojitými uvozovkami, tvořenými jednoduchými i dvojitými znaky. Řetězce mohou procházet přes více řádků.
>>> """Toto je jedna možnost.""" >>> '''Toto je druhá možnost.'''
Uvnitř řetězce s trojitými uvozovkami mohou být uvozovky jednoduché i dvojité:
>>> ''' "Ach ne", zvolala, "Benovo kolo je rozbité" ''' ' "Ach ne", zvolala, "Benovo kolo je rozbité" ' >>>
Trojité uvozovky se používají pro dokumentační řetězce (docstrings). Docstring je řetězec, umístěný jako první text v modulu, funkci, třídě nebo v definici metody:
def mocnina (m, n=3):''' Funkce počítá n-tou mocninu s pevně nastaveným exponentem n=3; lze jej změnit '''
Informaci o funkci získáme evokací (voláním, neboli také "aplikací") vestavěné metody
>>> print(mocnina.__doc__) Funkce počítá n-tou mocninu s pevně nastaveným exponentem n=3; lze jej změnit
Dokumentačního řetězce použijeme k získání stručné informace o jakémkoli vestavěném objektu (funkci):
>>> print(len.__doc__) Return the number of items in a container.
prefixes = "JKLMNOPQ" suffix = "ack"for letterin prefixes:
fruit = "banana" count = 0a zobecněte ji tak, aby přijímala řetězec a písmeno jako argument a vracela počet výskytů písmena v řetězci. Řešení vložte do skriptufor charin fruit:if char == 'a': count = count + 1
V následujících úlohách použijeme k ověření správnosti vašeho řešení doctesty, se kterým jsme se seznámili v kapitole 5.10. Vytvořte soubor se jménem
Přidávejte těla funkcí tak, aby prošla zkouškou doctestů. Ty budou u některých výsledků vyžadovat i apostrofy. Přičtete je k výstupu:if __name__ == '__main__':import doctest doctest.testmod()
print("'" + <výstup> + "'")nebo použijte funkci return <výstup>
Návštěva stránky String Methods může být v případě potřeby prospěšná.
def reverse (s): """ >>> reverse('happy') 'yppah' >>> reverse('Python') 'nohtyP' >>> reverse('') '' >>> reverse('P') 'P' """
Jednoduché řešení úsekovým operátorem
def mirror (s): """ >>> mirror ('good') 'gooddoog' >>> mirror ('yes') 'yessey' >>> mirror ('Python') 'PythonnohtyP' >>> mirror ('') '' >>> mirror ('a') 'aa' """
Prosté spojení dvou řetězců.
def is_palindrome (s): """ >>> is_palindrome('aclr-bba') True >>> is_palindrome('abab') False >>> is_palindrome('tenet') True >>> is_palindrome('banana') False >>> is_palindrome('straw warts') True """
Použijete řešení ad a).
def remove_letter (letter, strng): """ >>> remove_letter ('a', 'apple') 'pple' >>> remove_letter ('a', 'banana') 'bnn' >>> remove_letter ('z', 'banana') 'banana' >>> remove_letter ('i', 'Mississippi') 'Msssspp' """
Lze řešit prostřednictvím idiomu
def count_sub (sub, s): """ >>> count('is', 'Mississippi') 2 >>> count('an', 'banana') 2 >>> count('ana', 'banana') 1 >>> count('nana', 'banana') 1 >>> count('nanan', 'banana') 0 """
Napoví stránka "String Methods".
def remove_sub (sub, s): """ >>> remove('an', 'banana') 'bana' >>> remove('cyc', 'bicycle') 'bile' >>> remove('iss', 'Mississippi') 'Missippi' >>> remove('egg', 'bicycle') 'bicycle' """
Napoví stránka "String Methods".
def remove_all (sub, s): """ >>> remove_all('an', 'banana') 'ba' >>> remove_all('cyc', 'bicycle') 'bile' >>> remove_all('iss', 'Mississippi') 'Mippi' >>> remove_all('egg', 'bicycle') 'bicycle' """
>>> "%s %d %f" % (5,5,5) >>> "%-.2f" % 3 >>> "%-10.2f %-10.2f" % (7, 1.0/2) >>> print(" $%6.2f\n $%6.2f\n $%6.2f" % (3, 4.5, 11.2))
Totéž proveďte pomocí funkce