pre up next title end end

6. Řetězce

  1. Složený datový typ
  2. Operace s řetězci
    1. Operace pro řetězce, entice a seznamy
    2. Vestavěné metody pro řetězce
    3. Metoda join
    4. Metoda split
  3. Modul 'string'
  4. Operátor 'in' a 'not in'
  5. Porovnávání řetězců
  6. Použití metod
  7. Sestavení funkce 'find'
  8. Formátování řetězců
    1. Interpolačním operátorem %
    2. Výměnným polem a metodou .format
    3. Formátovaným literálem (f-stringem)
  9. Formátování výstupů
  10. Únikové sekvence
  11. Dokumentační řetězce
  12. Glosář
  13. Cvičení

6.1 Složený datový typ

Řetězce (strings) jsou neměnitelné sekvence znaků Unicode, vymezené uvozovkami - jednoduchými, dvojitými či trojitými.
Výraz "bim" "bam" je automaticky konvertován na "bimbam".

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í len, která vrací počet znaků v řetězci:

>>> 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

6.2 Operace s řetězci

6.2.1   Operace pro řetězce, entice a seznamy

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 + však s řetězci pracovat umí, i když jinak, než bychom očekávali. Pro řetězce, entice a seznamy představuje operátor + příkaz zřetězení (concatenation), což je spojení dvou operandů jejich připojením těsně k sobě. Například:

>>> "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:]
print(new_greeting)
'Hello all world!'

Řešením je zřetězení vložené části s úseky řetězce greeting. Tato operace nemá žádný vliv na původní řetězec.

Operátor násobení * rovněž pracuje s řetězci, enticemi i seznamy, způsobuje jejich zmnožení. Jeden z operandů musí být sekvence, druhým operandem musí být celé číslo, například:

>>> 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]

6.2.2  Vestavěné metody pro řetězce

Kromě společných procedur pro řetězce a seznamy existuje také velké množství vestavěných metod, speciálně určených pro řetězce, které většinou evokujeme sestavou  'řetězec'.metoda():

  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'

6.2.3  Metoda join

Z řetězce umíme vytvořit seznam (list(arg)) a ze seznamu řetězec (str(arg)), dokonce to umíme udělat jedním tahem:

>>> str (list("Žabička"))
"['Ž', 'a', 'b', 'i', 'č', 'k', 'a']"

Metoda join vrací řetězec, složený (concatenated) z prvků zadaného iteráblu (list, tuple, string, set a slovník). Prvky iteráblu musí být typu 'string'.

  'separ'.join(iteráble)     # 'separ' je vkládaný separátor                 

Chceme-li z rozsypaného čaje sestavit zase žabičku, použijeme metodu join :

>>> 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 .join() má zavádějící název. Jak vidíme, umí nejen spojovat ale i rozdělovat s vloženými znaky nebo mezerami.

6.2.4  Metoda split

Metoda .split() rozloží řetězec na seznam úseků (substringů) v závislosti na zadaném separátoru. Separátorem může být libovolný znak řetězce - jenž se ve vráceném seznamu nahradí čárkou.

    string.split(separátor, počet jeho použití) 

Atributy metody split()jsou nepovinné. Implicitní hodnotou separátoru je mezera: string . split().
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)                  # 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í ...']
Zajímavé případy:
>>> 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 Thonny a pohrávat si s variacemi uvedených ukázek.


6.3 Modul string

Modul string obsahuje další užitečné objekty pro manipulaci s řetězci. Jako obvykle, modul musíme importovat dřív než jej použijeme:

>>> import string

Obsah modulu zjistíme vestavěnou fcí dir se jménem modulu jako argument:

>>> 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 ascii_lowercase (kde se písmeno "ch" nevyskytuje - stejně jako česká písmena s diakritikou).

>>> is_lower("ch")
False

Metoda string.capwords(str [, sep=None]) rozdělí řetězec na jednotlivá slova (podle zadaného separátoru), počáteční písmena nahradí velkými a znovu spojí jednotlivá slova do jednoho řetězce. Použije-li se jako separátor znak, který není v původním řetězci obsažen, metoda vrátí řetězec s malými písmeny. Bez separátoru odstraní přebytečné mezery

>>> string.capwords("Honolulu  ", "o")
'HoNoLulu  '
>>> string.capwords("    Hono Lu  lU", "čau")
'    hono lu  lu'
>>> string.capwords("  Honolulu    ")
'Honolulu'

6.4 Operátor in a not in

Operátor příslušnosti in, not in přezkoumá, zda je zadaný řetězec součástí jiného:

>>> 'p' in 'apple'
True
>>> 'i' in 'apple'
False
>>> 'ap' not in 'apple'
False
>>> 'pa' not in 'apple'
True
Vš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 in a zřetězení můžeme napsat funkci, která odstraní všechny samohlásky z řetězce:

def remove_vowels(str):
    samohl = "aeiouyAEIOUY"
    str_bez_samohl = ""             # akumulátor
    for letter in str:
        if letter not in samohl:
            str_bez_samohl += letter
    return 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.


6.5 Porovnávání řetězců

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":
   print ("Ano, banány máme!")
print("Žádný takový!")

Jiné relační operátory jsou užitečné při uspořádávání slov podle abecedy:

if word == "banana":
   print("Your word, " + word + ", comes before banana.")
elif word > "banana":
   print("Your word, " + word + ", comes after banana.")
else:
   print("Maybe, we have bananas!")

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(), max(), ord() a chr():

>>> min("žoužel"), max("žoužel")
('e', 'ž')
>>> ord(min("žoužel")), ord(max("žoužel"))
(101, 382)
>>> chr(101), chr(382)
('e', 'ž')

6.6 Použití metod

Řetězce jsou sice neměnitelné ale lze libovolně upravovat jejich (často interně vytvářené) kopie. Pro tento účel existuje řada funkcí a metod.

Metoda  .removeprefix/suffix()

Těmito metodami lze změnit začátek a konec řetězce:

>>> "some Text".removeprefix("some ")
'Text'
>>> "some Text".removesuffix("Text")
'some '

Metoda  .replace()

Metoda string.replace(old, new [,count]) vytvoří kopii zadaného řetězce, v němž nahradí stávající substring novým substringem a to pro zadaný počet substringů (implicitně pro všechny).

>>> ring = "horo, horo, vysoká jsi"
>>> (fing := ring.replace("horo", "Horo", 1))
'Horo, horo, vysoká jsi'

Použitím metody replace lze částečně kompenzovat neexistenci procedury remove pro řetězce:

>>> 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 string

def remove_punct(s): 
    s_without_punct = ""     proměnná zvaná akumulátor
    for letter in s:
        if letter not in string.punctuation:
            s_without_punct += letter
    return s_without_punct
	
str = "Až na severní pól, běží liška!"	
print(remove_punct(str))

# Ctrl-S, F5 v IDLE:
Až na severní pól běží liška
Poznámka:
>>> import string as str
>>> str.punctuation
"!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~"
Cvičení: Můžeme si definovat vlastní soubor znaků, napříkad "žšěíó".
Pro jeho použití upravte funkci remove_punct(s).

Metoda  .find

Vrací index prvního výskytu zadaného substringu v prohledávaném řetězci. Schéma volání metody find (parametry v hranatých závorkách jsou nepovinné) je toto:

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 find je ve skutečnosti všestrannější než naše uživatelská funkce. Umí nalézt i části řetězců, nejenom pouhé znaky:

>>> 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 la nevyskytuje v intervalu od 1 do 15 (nikoliv včetně).

Metoda  .count

Vestavěnou metodu count použijeme při počítání výskytu zadaného znaku či skupiny znaků v řetězci:

string.count(value [, start [, end]])
>>> "abrakadabra".count("a")
5
>>> "abrakadabra".count("ra")
2
>>> "Až na severní pól".count(" ")
3

6.7 Sestavení funkce  find

Uživatelská funkce find přijme znak a nalezne index místa, kde se znak nachází. Není-li znak nalezen, funkce vrací -1.

def find(strng, ch):
    index = 0
    while index < len(strng):
        if strng[index] == ch:
            return index
        index += 1
    return -1

V této funkci se opět setkáváme s příkazem return uvnitř smyčky. Je-li str[index] == ch, je funkce ukončena předčasným přerušením smyčky.

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 = start
    while index < len(strng):
        if strng[index] == ch:
            return index
        index += 1
    return -1

Volání find1("banana","a",2) nyní vrátí pozici prvního a za indexem 2.

Funkci si vylepšíme úpravou parametru start. Připojením hodnoty z něj učiníme paramter s počáteční hodnotu, který je volitelný v tom smyslu, že jej můžeme při volání případně vynechat:

def find2(strng, ch, start=0):
    index = start
    while index < len(strng):
        if strng[index] == ch:
            return index
        index += 1
    return -1

Výsledek volání find2("banana", "a", 2) bude stejný jako find1("banana", "a", 2), zatímco při volání find2("banana", "a") bude parametr start nastaven na počáteční hodnotu 0.

Přidáním dalšího volitelného parametru do fce find zajistíme prohledávání jak dopředu, tak dozadu:

def find3(strng, ch, start=0, step=1):
    index = start
    while 0 <= index < len(strng):
        if strng[index] == ch:
            return index
        index += step
    return -1

Zadání hodnoty -1 pro step způsobí zmenšování stavu počítadla. Pro tuto změnu bylo nutné ošetřit jak horní tak i dolní mez proměnné index.


6.8 Formátování řetězců

6.8.1 Interpolačním operátorem %

Starší a v Pythonu 3.x stále použitelný způsob formátování řetězce je s použitím interpolačního operátoru % spolu s konverzními specifikacemi.

Konverzní specifikace jsou znaky, které zastupují zamýšlený formát vkládané hodnoty, například:

Schema formátování řetězce vypadá takto:

"řetězec se specifikacemi" % (hodnoty specifikací)

Část řetězec se specifikacemi obsahuje kombinaci textu a konverzních specifikací. Následuje samotný interpolační operátor % a za ním výčet hodnot, dosazovaných za konverzní specifikace. Závorky jsou nepovinné, je-li hodnota pouze jedna.

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 %s, která označuje řetězec. K ní se přiřazuje jediná hodnota "Arthur" a není uzavřena v závorkách.

Ve druhém příkladě má name hodnotu řetězce "Alice" a age má hodnotu celého čísla 16. Tyto se přiřazují ke dvěma konverzním specifikacím %s a %d; druhá specifikace je označením celého dekadického čísla.

Ve třetím příkladě mají proměnné n1 a n2 celočíselné hodnoty 4 a 5. Ve formátovaném řetězci jsou čtyři konverzní specifikace: tři %d a jedna %f. Písmeno f naznačuje, že příslušná hodnota má být ve tvaru čísla s plovoucí desetinnou čárkou. Čtyři hodnoty, které se vztahují k uvedeným čtyřem konverzním specifikacím jsou: 2**10,n1,n2 a n1*n2.

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 \t (viz tab. v 6.14):

i = 1
print("i\ti**2\ti**3\ti**5\ti**10\ti**20")   # záhlaví
while i <= 10:
   print(i,'\t',i**2,'\t',i**3,'\t',i**5,'\t',i**10,'\t',i**20)
   i += 1    

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 \t, které selhává, jakmile hodnoty výsledků zaberou 8 míst:

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 = 1 
print("%-4s%-5s%-6s%-8s%-13s%-15s" %
    ('i', 'i**2', 'i**3', 'i**5', 'i**10', 'i**20'))
while i <= 10:
    print("%-4d%-5d%-6d%-8d%-13d%-15d" % (i, i**2, i**3, i**5, i**10, i**20))
    i += 1    

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 (-) za každou konverzní specifikací určuje zarovnání zleva. Číselné hodnoty určují minimální délku, takže %-13d je minimálně třináctimístné číslo zarovnané zleva.


6.8.2 Výměnným polem a metodou .format

Novější způsob formátování výstupu je pomocí metody str.format() v sestavě

"ř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 {}. Nejjednodušší možná forma výměnného pole jsou prázdné složené závorky { }. Vše, co je mimo těchto závorek, je považováno za text, který je v nezměněném stavu kopírován do výstupu.

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 .format(). Tvoří-li čísla řadu 0, 1, 2, ..., lze je vynechat.

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í
!s, které volá funkci str(), jež vrací objekt coby řetězec
!r, které volá funkci repr(), jež vrací řetězec obsahující tisknutelnou prezentaci objektu
!a, které volá funkci ascii(), jež vrací řetězec, jehož non-ASCii znaky jsou nahrazeny escape sekvencí.

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:
šířku - pole pro číselnou hodnotu
výplň - libovolný znak kromě závorek { }; následuje pokyn pro zarovnání
zarovnání - vlevo (<), vpravo (>), na střed (^) a mezi(=) signum a číslici
signum - +, -, " ", (také # a 0)
přesnost - počet desetinných míst čísla: . údaj
typ - určuje způsob prezentace dat, například b je pro binární formát, d je pro decimální celé číslo, f pro formát float

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 hvězdičkové rozbalení:

>>> 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
>>>

6.8.3 Formátovaným literálem (f-stringem)

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ě f-string. Literál f-stringu se uvozuje písmenem f nebo F a lze použít obdobné konverze argumentů (!s, !r, !a) jako u předchozího způsobu formátová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 { }. Zatímco u předchozího způsobu odkazoval obsah těchto závorek pouze na konstantní hodnotu, u f-stringu může odkazovat také na výraz, funkci a metodu.

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'

6.9 Formátování výstupů

Formátování výstupů hodnot typu integer (d), float (f) a string (s) je uvedeno v následující tabulce (pro hodnoty mil = 1000000, mld = 1000000000, flt = 2.71828 a string = "aha"). Následující ukázky lze použít i bez příkazu "print".

   Hodnoty  Formát    Příklad použití    Výstup
   mil = 1000**2   {:,}    Comma separator:
            print(f'{mil:,}')
 1,000,000
   mld = 1000**3   {:.2e}    Exponent notation:
            print(f'{mld:.2e}')
 1.00e+09
   flt = 2.71828   {:.2f}   Format float:
            print(f'{flt:.2f}')
 2.72
   flt = 2.71828   round()              print(round(flt, 2))  2.72
   0.35  {:.2%}   Procenta:
             print(f'{0.35:.2%}')
 35.00%
   x,y = string, 9  {x:>y}    Dorovnání vlevo:
             print(f'{string:*>9}')
 ******aha
   x,y = string, 9   {x:<y}    Dorovnání vpravo:
             print(f'{string:*<9}')
 aha******
   x,y = string, 9   {x:^y}    Zarovnání na střed:
             print(f'{string:*^9}')
 ***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í f-stringu pro celé či desetinné číslo.

>>> x = 3; f"{x := 8}"
'       3'              # řetězec o délce 8 (včetně čísla 3)

6.10 Únikové sekvence

Ú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 '\t' si ukážeme v následující ukázce:

>>> strg = 'a\tb\nA\tB'
>>> print(strg)
 a	 b
 A	 B

Takzvaný raw string potlačuje vliv zpětných lomítek, potažmo escape sekvencí v řetězci. Formát "raw string" vytvoříme předsazením znaku r, případně R před zápis řetězce.

>>> strg = r'a\tb\nA\tB'    # zpětné lomítko je běžný znak
>>> print(strg)
 a\tb\nA\tB

6.11 Dokumentační řetězce

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
    '''
    print(m**n)

Informaci o funkci získáme evokací (voláním, neboli také "aplikací") vestavěné metody .__doc__ pro objekt funkce:

>>> 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.

6.12 Glosář

sekvence (sequence)
Uspořádaná množina prvků. Podmnožina této množiny se nazývá subsekvence.
index
Interní hodnota, použitá k označení prvku uspořádané řady, na příklad znaku v řetězci.
traverzovat (traverse)
Probírat postupně jednotlivé prvky dané řady a s každým provést obdobnou či stejnou operaci.
úsek (slice)
Část řetězce, vymezená rozsahem indexů.
dokumentační řetězec (docstring)
Řetězec, uvedený na prvním řádku funkce nebo modulu (a jak uvidíme později i třídy a metody). Dokumentační řetězce vhodně spojují programový kód s jeho komentářem. Používají se také pro automatické testování kódu s modulem doctest.

6.13 Cvičení

  1. V návaznosti na odstavec 6.7 upravte skript tak, aby se Ouack a Quack vytiskly správně:
    prefixes = "JKLMNOPQ"
    suffix = "ack"
    
    for letter in prefixes:
        print(letter + suffix)
    
  2. Zapouzdřete následující sekvenci příkazů do funkce count_letters_acc
    fruit = "banana"
    count = 0
    for char in fruit:
        if char == 'a':
            count = count + 1
    print(count)
    
    a 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 skriptu whatLetters_str.py
  3. Tutéž úlohu (výskyt znaků) řešte vestavěnou metodou string.count(letters), která počítá výskyt nejenom písmen ale i zadaných substringů.
  4. 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 stringtools.py a na jeho spodní okraj vložte tento veršíček:

    if __name__ == '__main__':
        import doctest  
        doctest.testmod() 
    
    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:
    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á.

    1. def reverse (s):
         """
         >>> reverse('happy')
         'yppah'
         >>> reverse('Python') 
         'nohtyP'
         >>> reverse('')
         ''
         >>> reverse('P')
         'P'
         """
      

      Jednoduché řešení úsekovým operátorem

    2. def mirror (s):
          """
          >>> mirror ('good')
          'gooddoog'
          >>> mirror ('yes') 
          'yessey'
          >>> mirror ('Python')
          'PythonnohtyP'
          >>> mirror ('')
          ''
          >>> mirror ('a')
          'aa'
          """
      

      Prosté spojení dvou řetězců.

    3. 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).

    4. 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 for .. in .. nebo metodou replace.

    5. 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".

    6. 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".

    7. 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'
          """
      
  5. Vyzkoušejte následující formátující řetězcové operace v konzole Pythonu a zaznamenejte výsledky:
    >>> "%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 .format().


previous up next title end end