Řetězce nejsnadněji zavedeme jako string literal pomocí uvozovek či apostrofů. Platí přitom pravidlo, že pro krátké řetězce na jednu řádku stačí uvozovky jednoduché, pro dlouhé řetězce na řádek více uvozovky trojté:
Všimněte přenosu zalomení řádku a mezer na začátku pro dvouřádkové ukázky!
Delší řetězce (bez formátování pomocí trojtých uvozovek) můžete zapsat i jinými způsoby, ale většinou to neprospívá čitelnosti:
Řetězce napsané hned za sebou jsou implicitně spojeny do jednoho:
>>> xs = "Ahoj, " "světe!"
>>> xs
'Ahoj, světe!'
Předchozí můžete dokonce rozložit na více řádek, pokud použijete vnější uzavírací (kulaté) závorky:
>>> xs = (
... "Ahoj, "
... "světe!"
... )
>>> xs
'Ahoj, světe!'
Také můžete řetězce „slepit“ operátorem + a na více řádek je roztáhnout pomocí iskejpovacího znaku \ před koncem řádku:
>>> xs = "Ahoj, " + \
... "světe!"
>>> xs
'Ahoj, světe!'
PS: Poslední dva triky platí i pro jiné kusy kódu než jen řetězce.
Mezi uvozovkami dvojtými a jednoduchými (apostrofy) není z hlediska použití v Python'u žádný rozdíl. Můžete je tudíž libovolně míchat, avšak kolizní uvozovky uvnitř řetězců je samozřejmě třeba iskejpovat (a to standardně pomocí zpětného lomítka \; které samotné pak tudíž musíte zapsat jako \\).
Jinak můžete použít (téměř) klasické céčkovské řídící sekvence (escape sequences):
Pokud naopak nechcete, aby se řídící sekvence uvnitř řetězců vyhodnocovaly (jako třeba uvnitř regexpů), musíte řetězec označit jako raw:
Prefix r i R fungují stejně.
Technicky vzato je to celé kapku složitější – Python se k nim dál chová jako k řetězcům, jen interně odiskejpuje zpětné lomítko, takže speciální znaky jimi přestanou být:
>>> xs = '123\n456'
>>> rxs = r'123\n456'
>>> xs
'123\n456'
>>> len(xs) # '\n' je jeden znak
7
>>> xs.count('\n')
1
>>> rxs
'123\\n456'
>>> len(rxs) # '\n' jsou dva znaky
8
>>> rxs.count('\n') # hledáme jeden znak (odřádkování)
0
>>> rxs.count(r'\n') # hledáme dva znaky (zpětné lomítko a písmeno n)
1
>>> rxs.count('\\n') # hledáme, co je skutečně uvnitř zapsáno
1
Jde o to, že sekvence \\ se z hlediska zacházení s ní dál chová jako jedno zpětné lomítko, jen je zrušeno provázání s následujícím znakem do podoby speciálního kódu.
Prázdný řetězec můžete vyrobit přímou notací (i když radši bez trojuvozovkové varianty :-)..
>>> s = ''
>>> s = ""
>>> s = ''''''
>>> s = """"""
..nebo též pomocí funkce str():
>>> s = str()
>>> type(s)
<class 'str'>
Řetězce v Python'u 3.X jsou automaticky unicodové => každý jeden viditelný znak je reprezentován proměnným počtem bajtů. Ale z hlediska běžné práce s řetězci jako sekvenčními typy (kterými řetězce jsou) nás to nemusí zajímat, protože se chovají právě tak, jak bychom čekali – nejmenší podjednotkou řetězce je právě jeden znak:
>>> xs = "Ahoj, světe!"
# délka sekvence
>>> len(xs)
12
# konkrétní prvek
>>> xs[3]
'j'
>>> xs[-3]
't'
# různé výřezy
>>> xs[3:9]
'j, svě'
>>> xs[3:9:2]
'j v'
>>> xs[3:]
'j, světe!'
>>> xs[-3:]
'te!'
# dotaz na výskyt prvku
>>> 'a' in xs
False
>>> 'A' in xs
True
>>> 'Ah' in xs
True
# dvě spojené kopie
>>> xs * 2
'Ahoj, světe!Ahoj, světe!'
Mimochodem „násobit“ řetězec můžete i nulou – výsledkem je nepřekvapivě řetězec prázdný.
PS: Komentáře zde pochopitelně nejsou součástí výstupu interaktivního interpretru, slouží pouze k popisu zde zapsaného kódu.
Po řetězcích se pak přirozeně prochází smyčkou:
>>> xs = "ahoj"
>>> for x in xs:
... print(x)
...
a
h
o
j
Případně pokud je důležitá i pozice výskytu znaku:
>>> xs = "ahoj"
>>> for i, x in enumerate(xs):
... print(i, x)
...
0 a
1 h
2 o
3 j
Jde to ale i obráceně:
>>> xs = "ahoj"
>>> for x in reversed(xs):
... print(x)
...
j
o
h
a
A dokonce i seřazeně:
>>> xs = "ahoj"
>>> for x in sorted(xs):
... print(x)
...
a
h
j
o
Řetězce patří mezi sekvence neměnitelné (immutable), což znamená, že jejich obsah po vytvoření již není možné měnit:
>>> xs = "řetězec"
>>> xs[3]
'ě'
>>> xs[3] = 'X'
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'str' object does not support item assignment
Spojením dvou řetězců však vzniká řetězec zcela nový, proto následující kód je v pořádku:
PS: Pojmenování následujících slajdů 9-12 je tedy poněkud zavádějící – všechny tam uvedené metody samozřejmě ponechávají originální řetězec netknut, pouze vezmou jeho textový „obsah“, pozmění ho uvedeným způsobem a vrátí ho jako řetězec zbrusu nový.
Počínaje Python'em 3.6, máme k dispozici velmi jednoduché a mocné formátování pomocí tak zvaných f-řetězců (tedy formátovaných řetězců). Prakticky ve všech ohledech se chová jako starší formátování pomocí funkce format(), jen je výrazně přehlednější:
>>> jméno, průměr = 'X', 1/3
>>> f"Prvek {jméno} by měl mít průměr {průměr:.3} cm."
'Prvek X by měl mít průměr 0.333 cm.'
Výše zmíněnou metodu format() je možno použít jak pozičně, tak za pomoci pojmenovaných argumentů (což je ukecanější, ale může to být v některých situacích přehlednější):
>>> "Prvek {0} by měl mít průměr {1:.3} cm.".format( 'X', 1/3 )
'Prvek X by měl mít průměr 0.333 cm.'
>>> "Prvek {} by měl mít průměr {:.3} cm.".format( 'X', 1/3 )
'Prvek X by měl mít průměr 0.333 cm.'
>>> "Prvek {jmeno} by měl mít průměr {prumer:.3} cm.".format( jmeno='X', prumer=1/3 )
'Prvek X by měl mít průměr 0.333 cm.'
Možnost vynechat označení pozice, pokud použijeme argumenty v zadaném pořadí, s sebou přinesl Python 3.1.
Formátování pomocí format() je mocné – jako parametr do {} můžete poslat prakticky cokoliv (seznam, slovník, instanci třídy...) a celkem rozumně s tím pak pracovat.
Starší způsob formátování, dosud podporovaný, ale určen k (pravděpodobnému) vyřazení, vypadá pro srovnání takto:
>>> '%(language)s has %(#)03d quote types.' % {'language': "Python", "#": 2}
'Python has 002 quote types.'
Kromě (původně) slabé podpory vstupních typů je jeho největším problémem předávání jedné složené hodnoty – výraz '%s' % msg selže, není-li proměnná msg jednoduchý typ, protože se ji pokusí rozdělit na prvky, které pak ale nebude mít kam přiřadit. Opraví to zápis s explicitní n-ticí '%s' % (msg, ) (byť má samozřejmě své mouchy), ale myslete na to, že.
Při zarovnávání textu pro výstup nejen na konzoli se vám asi budou hodit následující tři řetězcové metody:
Je poměrně „zajímavé“, že přes armádu metod na rozpoznávání, zda řetězec obsahuje jen a pouze čísla (isdecimal(), isdigit(), isnumeric(); mezi čísla se totiž počítají i všemozné historické zápisy zahrnuté do Unicodeu), neexistuje na řetězci metoda, která by řekla, zda představuje reálné číslo.
Nejuniverzálnějším – a také zdaleka nepřímočařejším – řešením tak zůstává starý klasický pokus o převod řetězce na číslo:
try:
float('-123.4')
except ValueError:
pass
PS: Pokud jste si s tvarem řetězce poměrně jistí, můžete místo toho někdy použít specializovanější postupy na jednu řádku jako například:
>>> '-123.4'.lstrip('-').replace('.', '', 1).isdigit()
True
Ta jednička v nahrazení je tam kvůli nečíslům typu 12.3.4 ^_~
Kromě metod na zjišťování „globálních“ vlastností řetězce z předchozího slajdu máme k dispozici i několik dalších metod zaměřených na vyhledávání podřetězců. První z nich umí počítat výskyty podřetězce v řetězci:
>>> 'řetězec'.count('t')
1
>>> 'řetězec'.count('e')
2
>>> 'řetězec'.count('W')
0
>>> xs = "Nesnesu se se sestrou."
>>> xs.count('se')
3
Zde konkrétně nepřekrývajících se podřetězců.
Metoda count(sub[, start[, end]])) má další dva nepovinné parametry určující výřez řetězce, v němž se má zadaný podřetězec hledat. Význam indexů je opět stejný jako u rozsahů.
Druhá skupina se umí vyjadřovat k poměrům na začátku a na konci řetězce:
>>> xs = "Nesnesu se se sestrou."
>>> xs.startswith('Nes')
True
>>> xs.startswith('Nest')
False
>>> xs.endswith('ou.')
True
>>> xs.endswith('ou')
False
Funguje to samozřejmě pro libovolně dlouhé podřetězce, takže třeba i pro jeden znak.
Potřebujete-li otestovat více možných začátků (či konců), obě metody akceptují i n-tici řetězců:
A tak trochu překvapivě umožnují obě metody i určení rozsahu, v jakém má k vyhledávání dojít:
str.startswith(prefix[, začátek[, konec]])
str.endswith(suffix[, začátek[, konec]])
Jde o klasické určení výřezu z řetězce str[začátek:konec] s nepovinným koncem.
Konkrétně vyhledávat podřetězce pak umožňuje metoda index a její pravostranná varianta rindex:
>>> xs = "There were 42 monkeys in the airplane."
>>> xs.index('e') # najdi první výskyt
2
>>> xs.rindex('e') # najdi poslední výskyt
36
>>> xs.index('e', 10) # hledej v xs[10:]
18
>>> xs.index('e', 10, 17) # hledej v xs[10:17]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: substring not found
>>> xs = "Nesnesu se se sestrou."
>>> xs.index('se')
8
>>> xs.rindex('se')
14
>>> xs.index('se', 12)
14
Neúspěch se projevuje tradičním pythoním způsobem, tedy výjimkou (zde ValueError). A slice-notace (tedy výběr podsekvence) funguje samozřejmě i pro rindex (který hledá vyhovující prvky směrem od konce, ale vrácené indexy jsou možná trochu překvapivě počítány standardně od začátku).
Pro tradicionalisty jsou zde i metody find a rfind, které pro záporný výsledek vrací tradiční -1:
>>> xs = "There were 42 monkeys in the airplane."
>>> xs.find('e') # najdi první výskyt
2
>>> xs.rfind('e') # najdi poslední výskyt
36
>>> xs.find('e', 10) # hledej v xs[10:]
18
>>> xs.find('e', 10, 17) # hledej v xs[10:17]
-1
>>> xs = "Nesnesu se se sestrou."
>>> xs.find('se')
8
>>> xs.rfind('se')
14
>>> xs.find('se', 12)
14
Slice-notace (tedy výběr podsekvence) funguje i pro rfind.
Podle potřeby jejich problémem nebo výhodou je, že v případě neúspěšného vyhledávání vrácená -1 je validní index do sekvence – její poslední prvek. Když se to zrovna hodí – fajn. Když ne, je pythoničtější vyhazovat výjimky, tedy použít spíše index a rindex.
Několik metod je zaměřených na práci s velikostí písmen:
Řetězec můžeme snadno zbavit na obou koncích nechtěných znaků:
>>> xs = '12 to by nešlo 24'
>>> xs.strip('1234')
' to by nešlo '
>>> xs.lstrip('1234')
' to by nešlo 24'
>>> xs.rstrip('1234')
'12 to by nešlo '
PS: Pro představu funkce – i když dosti náročnou – si můžete v duchu nahradit operaci strip() za smyčku nad všemi prvky všech permutací prvků jejího parametru a pokus o odstranění každého z nich z konce řetězce.
Bez udání parametru jsou výchozí hodnotou do všech tří funkcí prázdné znaky (whitespace):
>>> xs = ' to by nešlo '
>>> xs.strip()
'to by nešlo'
>>> xs.lstrip()
'to by nešlo '
>>> xs.rstrip()
' to by nešlo'
Jelikož metoda strip() z předchozího slajdu dokáže být pro někoho asi poněkud matoucí, Python 3.9 přinesl pro úpravu konců řetězců dvě nové průhlednější:
Pro některé typy úloh se hodí nahrazovat znaky pomocí překladové tabulky. Tu je třeba nejdříve vyrobit (statickou) metodou řetězce maketrans() a následně pak aplikovat na požadovaný text. Příklad odstranění (některých) ne-ASCII znaků:
# příprava překladové tabulky
nonASCII = "áâàǎăãäāåąčĉçċćďđéêèěėëēęġğĝģĥħíîìīĩĭıïįĵķľĺŀłňńņʼnŋñóôòŏöőōõøřŕŗšśŝşťţŧúûùůŭüűūũųŵýŷÿžżźÁÀǍĂÃÄĀÅĄČĈÇĊĆĎĐÉÊÈĚĖËĒĘĠĞĜĢĤĦÍÎÌĪĨĬİÏĮĴĶĽĹĿŁŇŃŅŊÓÔÒŎÖŐÕŌØŘŔŖŠŚŜŞŤŢŦÚÛÙŮŬÜŰŪŨŲŴÝŶŸŽŻŹ"
ASCII = "aaaaaaaaaacccccddeeeeeeeegggghhiiiiiiiiijkllllnnnnnnooooooooorrrsssstttuuuuuuuuuuwyyyzzzAAAAAAAAACCCCCDDEEEEEEEEGGGGHHIIIIIIIIIJKLLLLNNNNOOOOOOOOORRRSSSSTTTUUUUUUUUUUWYYYZZZ"
transtab = ''.maketrans(nonASCII, ASCII)
# aplikace překladové tabulky
ys = xs.translate(transtab)
PS: Zrovna odnabodeníčkování řeší kupříkladu i knihovní funkce unicodedata.normalize('NFD', 'svět').encode('ascii', 'ignore').decode('ascii'), nicméně to je hodně oklikou a musíte vědět něco o normalizaci v Unicodu a vůbec.
Znaky, které nejsou zanesené v překladové tabulce, projdou procesem beze změny:
Metoda translate() umí také převádět vstupní znaky na libovolně dlouhé řetězce! Překladovou tabulku je v tomto případě nutno zadat pouze jedním parametrem – slovníkem, jehož klíči jsou jednotlivé znaky (nebo jejich unicodové číselné ekvivalenty):
Řetězec můžeme podle zadaného podřetězce rozdělit na více částí. Nejobecnější metodou je split():
>>> xs = "Ahoj, světe! Jak se máš?"
>>> xs.split()
['Ahoj,', 'světe!', 'Jak', 'se', 'máš?']
>>> xs.split(' ')
['Ahoj,', 'světe!', 'Jak', 'se', 'máš?']
>>> xs.split(' ', 2)
['Ahoj,', 'světe!', 'Jak se máš?']
>>> xs.split(',')
['Ahoj', ' světe! Jak se máš?']
>>> xs.split(' s')
['Ahoj,', 'věte! Jak', 'e máš?']
Bez udání parametrů rozdělí split() zadaný řetězec podle prázdných znaků (whitespaces).
Druhý nepovinný parametr určuje maximální počet rozdělení, ke kterým dojde.
split() vrací seznam.
Pro srovnání ještě metoda rsplit() – chová se téměř úplně stejně jako split(), pouze rozřezává řetězce zprava doleva:
>>> xs = "Ahoj, světe! Jak se máš?"
>>> ys = xs.split()
>>> ys
['Ahoj,', 'světe!', 'Jak', 'se', 'máš?']
>>> ' '.join(ys)
'Ahoj, světe! Jak se máš?'
Syntaxe je tedy 'SEPARÁTOR'.join( ITERABLE ) (kde ITERABLE je jakýkoli objekt schopný vracet své členy po jednom, v tomto případě seznam).
>>> xs = " Hello World, I am here. "
>>> xs
' Hello World, I am here. '
>>> ' '.join( xs.split() )
'Hello World, I am here.'
Metodě [r]split() trochu podobná metoda partition(), resp. rpartition(), rozdělí zadaný řetězec podle podle prvního, resp. posledního, výskytu udaného separátoru:
>>> xs = "Ahoj, světe! Jak se máš?"
>>> xs.partition('e')
('Ahoj, svět', 'e', '! Jak se máš?')
>>> xs.rpartition('e')
('Ahoj, světe! Jak s', 'e', ' máš?')
>>> xs.partition('Jak')
('Ahoj, světe! ', 'Jak', ' se máš?')
Narozdíl od split() tedy partition nezahodí separátor a navíc vrací vždycky jen a pouze trojci.
A to i když se separátor v řetězci nevyskytuje!
>>> xs.partition('E')
('Ahoj, světe! Jak se máš?', '', '')
K dispozici máme ještě metodu specializovanou na rozdělování řetězců obsahujících odřádkování:
Všimněte si odlišného chování k poslednímu \n!
Pro operaci s řetězci na úrovni jednotlivých znaků slouží dvě standardní funkce ord() a chr().
Funkce ord() převede zadaný jeden znak (tedy řetězec o délce jedna) na codepoint-číslo odpovídající tomuto znaku v Unicode-tabulce:
>>> ord('a')
97
>>> ord('ř')
345
Komplementární funkce chr() převádí naopak zadané celé číslo představující unicodový codepoint na odpovídající znak (tedy řetězec délky jedna):