Příkaz print a něco o řetězcích

Příkaz print

Jen stručně: Zavoláním příkazu print se na textovém výstupu programu objeví textová podoba jeho argumentů. Ty jsou odděleny mezerou a na konci se ještě přidá nový řádek. Proto

print(a,'+',b,'=',a+b)
print(a,'-',b,'=',a-b)

vypíše pro a=5 a b=2 tyto dva řádky

5 + 2 = 7
5 - 2 = 3

Lze ale změnit oddělovač (separátor) například na prázdné místo (řetězec '')

print(a,'+',b,'=',a+b,sep='')

kdy se vypíše

5+2=7

Podobně lze uvedením end='' zabránit vypsání nového řádku na konci výstupu příkazu print. Nebo jej volbou end=' ' přeměnit na mezeru. Nastavení end=... lze libovolně kombinovat s požadovanou volbou sep=....

Cvičení: Pro vhodné a,b,c zařiďte aby print vypsal

12345 * 9 + 6 = 111111
[3]:
# zde si to vyzkoušejte
a, b, c = 12345, 9, 6
print()

Řetězce

Ačkoli bude těžitě našeho snažení ve výpočtu numerických hodnot, budeme občas muset pracovat i nečíselnými informacemi. Již jen v okamžiku, kdy potřebujeme své výsledky uložit pro další použití nastává několik situací, které spadají mezi práci s řetězci:

  • textová prezentace čísleného výstupu vyžaduje tzv. formátování, tedy někdy potřebujeme rozhodnout, zda máme výsledek zapsat jako 101.5, 101.4997214, 1.014997214e2

  • pokud jde o tabulovaná data, je potřeba řešit mezery mezi sloupci

  • občas potřebujeme přidat komentář, co který sloupec znamená

  • nebo přidat mezi čísla nějaký daší vysvětlující text

  • vytvářet názvy souborů programem

Pokud naopak chceme číselné hodnoty z textového souboru načíst, může sitauace vyžadovat předzpracování dat na úrovni řetězců. Navíc řatězce obecně představují srozumitelný nenumerický datový typ a lze na nich realizovat zajímavé algoritmy.

Pro naše potřeby se omezíme na minimum. V úvodní části představíme nezbytné základy a až se seznámíme s poli, vrátíme se k některým dalším operacím s řetězci.

Řetězcové literály

Když napíšeme sekvenci znaků mezi úvodovky ("abc") nebo apostrofy ('abc') a přiřadíme ji do proměnné

jednotka = 'kg'

stane se jednotka identifikátorem proměnné, která je typu str.

Dědictvím jazyka C je způsob vkládání speciálních znaků do řetězce.

retezec = "a\tb\n1\t2"
print(retezec)

obsahuje speciální znak přechodu na nlový řádek '\n' tabulátor '\t', takže vytiskne

a   b
1   2

Pokud chceme do řetězce vložit apostrof, je nejsnazší jej "obalit" úvozovkami

doba_konani = "podzim '23"

a obráceně

zvolani = '"miluji" Python'

Ještě flexibilnější je trojice úvozovek nebo apostrofů. Ta umožňuje do řetězcového literálu čitelně vložit i nové řádky

html_text = '''<html>
 <body>
   <h1>Hola!</h1>
 </body>
</html>
'''

je ekvivalentí zápisu

html_text = '<html>\n <body>\n  <h1>Hola!</h1>\n </body>\n</html> \n'

(To, že je první řádek nepohodlně odsazen lze řešit použitím tří apostrofů následovaných znakem backslash: html_text='''\ a pak můžeme pokračovat na novém řádku, aniž by řetězec tímto novým řádkem začínal.)

Formátované řetězce

Poměrně nedávno se v Pythonu objevily f-strings (formátované literály, interpolované řetězce). Ty umožňují do řetezce vložit identifikátor hodnoty proměnné (nebo celý výraz) a popsat, jak má výsledné číslo vypadat (počet platných cifer, zarovnání atd). Ačkoli je mnoho dalších způsobů, jak dosáhnout stejného výsledku, budeme používat výhradně tento.

Pokud před zápis řetězcové konstanty zapíšeme písmeno f, vyhledají se v tomto řetězci výrazy uzavřené ve složených závorkách a ty jsou nahrazeny jejich hodnotou (tzv. string interpolation)

Jednoduchý příklad:

print(f'{a}+{b}={a+b}')

vypíše pro odpovídající hodnoty proměnných

1+2=3

Navíc v novějších verzích Pythonu (>=3.8)

print(f'{a+b=}')

vypíše

a+b=3
[1]:
a, b = 1, 2
print(f'{a}+{b}={a+b}')

1+2=3

Lze ovlivnit, kolik znaků výpis čísla zabere, jak bude centrován a nebo např. kolik desetinných míst chceme. Např. ve jménech souborů pak chceme, aby místo mezer byly u čísel nuly.

Další informace jsou např. zde a zde

Následující příklad ukazuje základní fomátování celých čisel a čísel reálných.

[12]:
print("celé číslo")
i = 123
print(f'{{i}}     :__{i}__')      # podtržítka slouží jen pro zviditelnění mezer ve výstupu
print(f'{{i:6}}   :__{i:6}__')    # 6 mist doprava
print(f'{{i:<6}}  :__{i:<6}__')   # 6 mist doleva
print(f'{{i:^6}}  :__{i:^6}__')   # 6 mist vycentrovat

print("\nběžné číslo")
x = 123.4567890123456
print(f'{{x}}     :__{x}__')
print(f'{{x:8.2e}}:__{x:8.2e}__')
print(f'{{x:8.2f}}:__{x:8.2f}__')
print(f'{{x:8.2g}}:__{x:8.2g}__')

print("\nkulaté číslo")
x = 12.4
print(f'{{x}}     :__{x}__')
print(f'{{x:8.2e}}:__{x:8.2e}__')
print(f'{{x:8.2f}}:__{x:8.2f}__')
print(f'{{x:8.2g}}:__{x:8.2g}__')

print("\nmalé číslo")
x = 12.4e-12
print(f'{{x}}     :__{x}__')
print(f'{{x:8.2e}}:__{x:8.2e}__')
print(f'{{x:8.2f}}:__{x:8.2f}__')
print(f'{{x:8.2g}}:__{x:8.2g}__')

print("\nvelké číslo")
x = 12.4e+12
print(f'{{x}}     :__{x}__')
print(f'{{x:8.2e}}:__{x:8.2e}__')
print(f'{{x:8.2f}}:__{x:8.2f}__')
print(f'{{x:8.2g}}:__{x:8.2g}__')

celé číslo
{i}     :__123__
{i:6}   :__   123__
{i:<6}  :__123   __
{i:^6}  :__ 123  __

běžné číslo
{x}     :__123.4567890123456__
{x:8.2e}:__1.23e+02__
{x:8.2f}:__  123.46__
{x:8.2g}:__ 1.2e+02__

kulaté číslo
{x}     :__12.4__
{x:8.2e}:__1.24e+01__
{x:8.2f}:__   12.40__
{x:8.2g}:__      12__

malé číslo
{x}     :__1.24e-11__
{x:8.2e}:__1.24e-11__
{x:8.2f}:__    0.00__
{x:8.2g}:__ 1.2e-11__

velké číslo
{x}     :__12400000000000.0__
{x:8.2e}:__1.24e+13__
{x:8.2f}:__12400000000000.00__
{x:8.2g}:__ 1.2e+13__

Cvičení: Vraťe se k příkladu "12345 * 9 + 6 = 111111" a použijte formátovaný řetězec

Záladní operace s řetězci

Podobně jako u číselných proměnných, pro založení proměnné obsahující řetězec použijeme přiřazovací příkaz, např.

str_a = 'retezec a'

Místo konstanty (literálu) 'retezec a' můža na pravé straně stát výraz. Ten se může skládat z binárních operací

  • +...spojování řetezců ('a'+'b' ---> 'ab')

  • *...opakování řetezců ('a'*3 ---> 'aaa')

a z funkcí, kterí vracejí řetězec.

Funkce str a char

Tou nejdůležitější je funkce str provádějící konverzi hodnoty libovolného typu na řetězec.

Poznámka: Podobnou roli má i funkce repr. Většinou vrací totožný řetězec jako funkce str, pokud ne, pak by funkce repr by měla vrátit řetězec obsahující více informací.

[6]:
import math
str(math.pi)
[6]:
'3.141592653589793'

Další zajímavou funkcí je chr. Tako konvertuje celé číslo na znak. Pravidla podle kterých jsou znaky očíslovány jsou věcí dohody. Důležitý standard pro čísla 0..127 se jemnoval ASCII, souvisel ještě s dálnopisným přenosem textů a přirozeně přešel i do říše počítačů. Znaky mezinárodní abecedy pak zahrnuje v Pythonu používané Unicode. Protože jde o kód binární, mají následující řádky 16 nikoli 10 znaků. Unicode představuje rozšíření ASCII a místo 128 přiřazuje čísla již >100 000 znakům. My si vypíšeme jen ty mezi 32 a 415. Znaky pod 32 jsou neviditelné řídíci znaky jako je nový řádek nebo tabulátor, další znaky si můžete prohlédnout na Wikipedii.

[2]:
print('     | 0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15')
print('-----|'+'-'*48, end='')
for i in range(32,127):
   if i%16==0:
      print(f'\n{i:>4} | ',end='')
   print(chr(i),end='  ')

     | 0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15
-----|------------------------------------------------
  32 |    !  "  #  $  %  &  '  (  )  *  +  ,  -  .  /
  48 | 0  1  2  3  4  5  6  7  8  9  :  ;  <  =  >  ?
  64 | @  A  B  C  D  E  F  G  H  I  J  K  L  M  N  O
  80 | P  Q  R  S  T  U  V  W  X  Y  Z  [  \  ]  ^  _
  96 | `  a  b  c  d  e  f  g  h  i  j  k  l  m  n  o
 112 | p  q  r  s  t  u  v  w  x  y  z  {  |  }  ~

Úloha: Vyzkoušejte, jaký znak se skrývá pod číslem 9825. (Použijte print a chr.)

Závěrečná poznámka: Ačkoli se řetězce skládají ze znaků, nemáme dovoleno řetězce měnit, i když chceme změnit jen jediný znak, musíme vytvořit novou hodnotu a do proměnné přiřadit. Řetězce ještě potkáme, až se naučíme pracovat s poli.