Notes and Talks/UJEP/PRG1/03

Řetězce, rozhodování, cykly

Proč se chybě v programu říká bug?

Inspekce proměnných v zápisníku Google Colab

Inspekce proměnných = sledování jejich hodnoty a typu při běhu programu.

pythonjméno = input('Jak se jmenujete? ')
bydliště = input('Kde bydlíte? ')
věk = int(input('Kolik je Vám let? '))

print(f'Dobrý den, pane/paní {jméno},')
print(f'bydlíte v městě {bydliště}')
věk = věk + 1
input() # pozastaveno
print(f'a za rok Vám bude {věk + 1} let.')

Vestavěné funkce

Systémové funkce, metody a moduly mají v Pythonu jména, která začínají a končí dvěma podtržítky. Např. modul __builtins__ (tento modul nemusíme importovat) obsahuje vestavèné funkce, výjimky a jiné:

pythonprint(__builtins__)
pythondir(__builtins__)
pythonhelp(__builtins__) # ojojoj

Např. vestavěné funkce min() nebo max() …

pythonhelp(min)
help(max)

… akceptují dva a více argumentů, nebo jeden seznam (list) hodnot:

pythonprint(min(3, 2))
print(min(3, 2, 4, 8))

seznam = [3, 2, 4, 8]
print(seznam)
print(type(seznam))
print(min(seznam))

Řetězce (strings)

Řetězec (string, str🐍) je neměnná (immutable) posloupnost znaků. Specielní (nestandardní) znaky lze zapisovat pomocí escape sekvencí🟢, a to i Unicode🐍:

pythons = 'line\n\talfa slon: \u03B1\U0001F418'
print(s)

Nebo můžeme vložit unicode přímo jako znak:

pythonslon = '🐘'
print(slon)

Řetězce lze spojovat,

pythons = 'sss'
t = 'ttt'
s + t

opakovat,

pythons = 'x '
n = 8
s * n

a hledat v nich podřetězce operátorem in:

python'ro' in 'Frodo'
python'ro' in 'Gandalf'

Typ str má celou řadu metod:

pythondir(str)
# help(str)

Například zaměňování:

pythonprint('Faramir'.replace('Fara','Boro'))

Nebo rozdělení řetězce na části:

pythonx,y,z = '3 4 5.0'.split() # Ha! Mnohonásobné přiřazení vlevo
print(x, y, z)

a mnohé další.

Rozhodování – větvení programu

Podmínky – např. porovnání dvou čísel – mají výsledek typu bool: False nebo True. Ale i jiné typy lze použít jako tzv. pravdivostní hodnoty. Např.:

Čísla: 0 je nepravda, ostatní čísla pravda

pythonx = 0
# x = 0.0
# x = 0.1
# x = 1
print('není nula' if x else 'je nula')

Řetězce: prázdný řetězec je nepravda, neprázdný pravda

pythons = ''
# s = '-'
# s = ' '
print('není prázdný' if s else 'je prázdný')

Seznamy: prázdný seznam je nepravda, neprázdný pravda

pythonl = []
# l = [0]
print('není prázdný' if l else 'je prázdný')

Podle jedné podmínky lze program větvit na dva různé bloky. Vnitřek bloků musí být odsazený. Typicky se v Pythonu odsazuje o čtyři mezery, ale v moderních editorech také jen o dvě mezery.

Větvení lze do sebe zanořovat:

pythonjméno = input('Jak se jmenujete? ')
věk = int(input('Kolik je Vám let? '))

AGE = 18
mladistvý = věk < AGE

if mladistvý:
    print(f'Dobrý den, mladý pane/slečno {jméno},')
    print('gratuluji k Vašemu mládí!')
else:
    print(f'Dobrý den, pane/paní {jméno},')
    print('gratuluji k Vaší moudrosti!')

if mladistvý:
    volba = input('Přejete si vodu? ')
else:
    volba = input('Přejete si vodu nebo vodku? ')

chciVodu = 'vodu' == volba

if mladistvý:
    if chciVodu:
        print('Zde je voda.')
    else:
        print('Zde je voda místo vodky.')
else:
    if chciVodu:
        print('Zde je voda.')
    else:
        print('Zde je vodka.')

Nebo takto:

pythonif chciVodu:
    print('Zde je voda.')
else:
    if mladistvý:
        print('Zde je voda místo vodky.')
    else:
        print('Zde je vodka.')

Podmínky lze také řetězit:

pythonx = 0 # 1, -1
if x < 0:
    print('x je záporné')
elif 0 < x:
    print('x je kladné')
# elif ...
else:
    print('x je nula')

Takže předchozí kód lze upravit takto:

pythonif chciVodu:
    print('Zde je voda.')
elif mladistvý:
    print('Zde je voda místo vodky.')
else:
    print('Zde je vodka.')

Cykly (smyčky) for .. in

Program lze cyklit: opakovat jeho část. První druh je tzv. for-cyklus, který provede kód (tělo cyklu, tzv. _iteraci_) právě jednou pro každý zadaný objekt:

pythonfor i in range(6): # range() je líný "seznam"
  print(i)

i (nebo jiné jméno) je tzv. řídící proměnná cyklu

pythonfor i in range(1, 10, 2): # lichá čísla
  print(i)
pythonfor i in range(1, 6):
  print('*' * i)
pythonfor c in 'abc🐘': # znaky v řetězci
  print(c)

Řetězec (a podobné kolekce) lze indexovat (přistupovat k prvkům podle jejich pořadí, pozice):

pythons = 'abc🐘'
for i in range(len(s)): # pozice (index) v řetězci
  print(s[i])           # znak na pozici i

A to i od konce, pomocí negativních indexů:

pythons = 'abc🐘'
for i in range(len(s)): # pozice (indexy) v řetězci
  print(s[-i-1])        # znak na pozici i

Cykly lze do sebe vnořit:

pythonfor i in range(6):    # vnější cyklus, řídicí proměnná i
  for j in range(8):  # vnitřní cyklus, řídicí proměnná j
    print('* ', end='')
  print()

Cyklus lze _předčasně_ ukončit příkazem break

pythonfor i in range(10):
  if 7 < i: # poslední byla sedmička
    break
  print(i)

Také lze vynutit předčasné pokračování cyklu příkazem continue

pythonfor i in range(10):
  if i % 2: # přeskoč lichá čísla
    continue
  print(i)

Cykly while

Druhý typ cyklu je tzv. while-cyklus, který provádí kód (tělo cyklu) tak dlouho, pokud je splněna daná podmínka:

python# stejné jako: for i in range(10):
i = 0         # počáteční hodnota
while i < 10: # podmínka
  print(i)    # tělo: první řádek
  i = i+1     # tělo: druhý řádek

Pozor na nekonečný cyklus!

pythoni = 0
while i < 10:
  print(i)
  i = i-1

Vstup a obsluha výjimek:

pythonmámTo = False
while not mámTo:
  try:    # začátek chráněného bloku
    i = int(input('Zadej celé číslo mezi jednou a deseti: '))
    if 1 <= i <= 10:
      mámTo = True
  except: # zde se zachytí výjimka
    pass  # prázdný příkaz

print(f'zadáno bylo {i=}')

Nebo takto:

pythonwhile True:   # nekonečný cyklus
  try:        # chráněný blok
    i = int(input('Zadej celé číslo mezi jednou a deseti: '))
    if 1 <= i <= 10:
      break   # předčasné (explicitní) ukončení cyklu
  except:
    print('Chyba, chybka, chybička ⚠️')

print(f'zadáno bylo {i=}')

Tento kód je užitečný, můžeme si z něj udělat funkci:

pythondef getInt(low, high):  # uživatelská funkce s paranetry low a high
  while True:
    try:
      number = int(input(f'Zadej celé číslo mezi {low} a {high}: '))
      if low <= number <= high:
        return number   # návrat z funkce
    except:
      pass

# použití funkce
i = getInt(10, 20)
print(f'zadáno bylo {i=}')
j = getInt(20, 40)
print(f'zadáno bylo {j=}')