comment up next how to end end

4. Opakované výpočty

  1. Podmínka while
  2. Podmínky if.. elif.. else
  3. Vnořené podmínky
  4. Příkaz return
  5. Rekurze I
  6. Iterace
  7. Smyčka for..
  8. Funkce range
  9. Funkce enumerate
  10. Funkce filter, map a reduce
  11. Funkce print
  12. Interní index elementu
  13. Glosář
  14. Cvičení

4.1 Podmínka  while

Počítače se často používají k automatickému výpočtu opakujících se úloh. Opakované provádění stejných nebo podobných úloh bez chyb je něco, co počítače dělají lépe než lidé.

Použití příkazu while si ukážeme na funkci countdown:

def countdown(n):           parametr jako počáteční stav počítadla
    while n > 0:            omezující podmínka
        print(n)
        n = n-1             změna stavu počítadla

Příkaz while se dá číst téměř jako prostý text: Pokud bude n > 0, vytiskni hodnotu n a potom ji zmenši o 1. Když se dostaneš k hodnotě n = 0, hodnocení podmínky končí.

Formálněji popíšeme tok výpočtu s příkazem while takto:

  1. Vyhodnoť podmínku while s výstupem False nebo True.
  2. Je-li hodnocení False, vystup ze smyčky while a pokračuj dalším příkazem (pokud existuje).
  3. Je-li hodnocení True, proveď všechny příkazy v těle podmínky a vrať se ke kroku 1.

Tělo podmínky tvoří všechny příkazy pod záhlavím podmínky se stejným odsazením.

Tento typ toku programu se nazývá smyčka, protože se opakovaně vracíme k počátku. Uvědomme si, že když je podmínka nepravdivá již při prvním běhu smyčkou, příkazy uvnitř smyčky se nikdy neprovedou.

Tělo smyčky by mělo měnit hodnotu jedné či více proměnných tak, aby se podmínka nakonec stala nepravdivou a smyčka skončila. Jinak by se opakovala do nekonečna, a byla by to nekonečná smyčka.

V případě funkce countdown(n) můžeme dokázat, že smyčka končí, protože víme, že hodnota n je konečná a že se při každém průchodu smyčkou zmenšuje, takže nakonec se musíme dostat k nule. V jiných případech to tak zřejmé být nemusí.

def sequence(n):
    while n != 1:
        print(n, end=", ")
        if n%2 == 0:         # n je sudé
            n = n//2
        else:              
            n = n*3+1
>>> sequence(4)
4, 2,

Podmínkou pro tuto smyčku je n!=1, takže bude rotovat tak dlouho, dokud nebude n=1, čímž se stane podmínka nepravdivá.

Při každém průchodu smyčkou program vrácí hodnotu n a zkontroluje, je-li sudá či lichá. Je-li sudá, je n děleno 2. Je-li lichá, nahradí se hodnotou n*3+1. Například, pro sequence(3) je výsledná posloupnost 3, 10, 5.0, 16.0, 8.0, 4.0, 2.0 .

Protože se n někdy zvětšuje, jindy zmenšuje, nemáme zřejmý důkaz, že n někdy dospěje k 1, nebo že program skončí. Pro jisté hodnoty n můžeme ukončení dokázat. Například, bude-li počáteční hodnotou mocnina 2, bude n stále sudé, dokud nedospěje k 1. V předchozím případě výsledná posloupnost takovou řadu (počínající číslem 16) obsahuje.

Odhlédneme-li od zmíněných čísel, je na místě otázka, zda umíme dokázat, že tento program je konečný pro všechny možné hodnoty n. Zatím se to nikomu nepodařilo!

Jiným příkladem použití smyčky while je traverzování po elementech seznamu:

# Výběr slov se sudým pořadím

slova = ["Copak", "je", "to", "za", "fešáka", "?"]

i = 0
délka = len(slova) 
while i < délka :
    if i % 2 == 1 :
        print(slova[i], end=", "") 
    i += 1
========== RESTART: F:\Codetest\HowTo\trump.py ==========
je, za, ?, 

Následující ukázka demonstruje použití pojmenovaného výrazu (walruss operator) v kombinaci s podmínkou while a vstupem uživatele:

while (user_input := input('Enter q or p: ')) != 'q':
    if user_input == 'p':
        print("Hello!")
========== RESTART: F:\Codetest\HowTo\trump.py ==========
Enter q or p: p
Hello!
Enter q or p: q
>>> 

4.2   Podmínky if.. elif.. else

K napsání užitečného programu potřebujeme mít možnost měnit chování programu v závislosti na splnění či nesplnění jistých podmínek.
Tyto podmínky se formulují pomocí relačních (kap. 2.8.2) a logických operátorů (kap. 2.8.3).

4.2.1 Podmínka if..

Tuto jednoduchou podmínku je vhodné použít jako součást jiné procedury, například funkce:

def odmocnina(x):
    if x >= 0:
        print ("odmocnina", x, "=", x**0.5)        # viz odst. 4.11

Stejně jako funkce a jiné složené příkazy se příkaz if skládá ze záhlaví a těla. Záhlaví začíná klíčovým slovem if, pokračuje booleovským výrazem neboli podmínkou a končí dvojtečkou.
Poté, co se podmínka vyhodnotí jako pravdivá, provede se odsazená část složeného příkazu.

>>> odmocnina(5)
odmocnina 5 = 2.23606797749979

4.2.2 Podmínka if .. else

Touto podmínkou realizujeme takzvané alternativní provedení, při němž existují dvě možnosti a podmínka určí, která z nich se provede:

x = int(input("Zadej číslo: "))     # ošetření vstupu z konzoly

if x % 2 == 0:                      # při splnění podmínky
    print (x, "je sudé")            # se provede odsazený příkaz
else:                               # při nesplnění podmínky
    print (x, "je liché")           # se provede tento příkaz 

Je-li zbytek po dělení dvěma roven nule, potom víme, že x je sudé a program tuto zprávu zobrazí. Není-li tato podmínka pravdivá, provede se druhá sada příkazů. Protože podmínka může být pouze pravdivá nebo nepravdivá, provede se určitě jedna z obou možností.

Alternativám říkáme větve protože jsou rozvětvením toku programu.

Mimochodem, kdybychom potřebovali často posuzovat "lichost" či "sudost" čísel, mohli bychom si tento prográmek "zabalit" do funkce:
def print_parity(x):
    if x%2 == 0:
        print(x, "je sudé")
    else:
        print(x, "je liché")

Podmínku if .. else lze také uplatnit jako infix mezi dvěma výstupy:

def print_parity(x):
    print(x, " je sudé") if x%2 == 0 else print(x, " je liché")    

Pro každou hodnotu x vrátí print_parity příslušnou zprávu. Při volání můžeme zadat jako argument jakýkoliv celočíselný výraz:

>>> print_parity(17)
17 je liché
>>> y = 41
>>> print_parity(y + 1)
42 je sudé

4.2.3 Podmínka if .. elif .. else

Někdy je více než dvě možnosti a my potřebujeme více než dvě větve. Použijeme seriově uspořádané (zřetězené) podmínky:

if x < y:
    print(x, "is less than", y)
elif x > y:
    print(x, "is greater than", y)
else:
    print(x, " and ", y, " are equal")

elif je zkratka "else if". Opět je provedena pouze jedna větev. Počet elif není omezen, příkaz else však smí být pouze jeden a musí být uveden jako poslední.

Podmínky jsou zkoumány jedna za druhou. Je-li první nepravdivá, prověřuje se další. Je-li některá pravdivá, provede se bezprostředně následující větev programu. Jestliže je pravdivých podmínek více, provede se jen první z nich.

4.2.4 Procedure if_case(choice)

Sekvencí podmínek if.., elif.., elif.., else lze simulovat v Pythonu chybějící proceduru switch case. Obdobné řešení pomocí slovníku je uvedeno v Kap. 11.8.

Mějme skript s funkcemi fce_a, fce_b, fce_c a s funkcí if_case(choice):

def fce_a():
    print("fce_a byla volána")
def fce_b():
    print("fce_b byla volána")
def fce_c():
    print("fce_c byla volána")

def if_case(choice):
    if   choice == 'a': fce_a()
    elif choice == 'b': fce_b()
    elif choice == 'c': fce_c()
    else: print("Neplatná volba")
Výstupem v konzole IDLE by mělo být:
===== RESTART: F:\Codetest\HowTo\ch-04\if_case.py =====
>>> if_case("c")
fce_c byla volána
>>> if_case(5)
Neplatná volba

4.3   Vnořené podmínky

Jedna podmínka může být vnořena do druhé. Předchozí trojité větvení můžeme realizovat také takto:

if x == y:
    print(x, "and", y, "are equal")
else:
    if x < y:
        print(x, "is less than", y)
    else:
        print(x, "is greater than", y)

Vnější podmínka má dvě větve. První větev obsahuje prostý příkaz k tisku. Druhá větev obsahuje další podmínku if, která má své vlastní dvě větve. Obě tyto větve jsou prostým voláním funkce print.

I když odsazení příkazů činí strukturu zápisu zřejmou, vnořené podmínky se velmi rychle stávají méně přehledné. Pokud můžeme, tak se jim raději vyhneme.

Vnořené podmínky můžeme často zjednodušit logickými operátory. Následující kód bude v další ukázce přepsán pro použití jen jedné podmínky:

if 0 < x:
    if x < 10:
        print("x is a positive single digit.")

K volání funkce print dojde pouze tehdy, splníme-li obě podmínky, můžeme tedy použít operátor and.

if 0 < x and x < 10:
    print("x is a positive single digit.")

Pro toto docela běžné seskupení podmínek poskytuje Python alternativní syntaxi, která je podobná zápisu v matematice:

if 0 < x < 10:
    print("x is a positive single digit.")

Tato podmínka je významově stejná jako složený booleovský výraz s vnořenou podmínkou.


4.4 Příkaz 'return'

Ve funkci s větvenými podmínkami s výhodou použijeme příkaz return:

def absolute_value(x):
    if x < 0:
        return -x
    else:
        return x

Protože jsou tyto příkazy v alternativních podmínkách, provedou se pouze jednou - jakmile se jeden z příkazů return provede, funkce končí bez provádění následných příkazů.

Naši funkci můžeme zapsat také stručněji. Místo příkazu else dáme přímo příkaz return.

def absoluteValue(x):
    if x < 0:
        return -x
    return x

Přesvědčme se, že tato fce pracuje stejně jako ta předchozí.

Kód, který je zapsán za příkazem return i kterékoliv další místo, kam se tok programu nedostane, se nazývá mrtvý kód.

Je dobré aby každá možná cesta funkcí narazila na příkaz return. V následující verzi absolute_value toto zajištěno není:

def absolute_value(x):
    if x < 0:
        return -x
    elif x > 0:
        return x

Tato verze není zcela správná, protože bude-li x rovno nule, žádná z podmínek není pravdivá a funkce končí, aniž by narazila na příkaz return; výslednou hodnotou je speciální hodnota zvaná None:

>>> print(absoluteValue(0))
None

None je jediná hodnota typu NoneType.


4.5 Rekurze I

Rekurze je technika, při které funkce volá (s jinými parametry) samu sebe . Funkci countdown(n) z odstavce 4.1 můžeme s pomocí rekurze zapsat takto:

def countDown(n):        # základním případem je zde argument n 
    if n < 1:            # omezující podmínka          
        return
    print(n)
    countDown(n-1)       # rekurzivní volání se změnou argumentu

Správně definovaná rekurze vyhovuje těmto dvěma požadavkům:

Pokud by rekurzivní volání nenarazilo na základní případ, šlo by o nekonečnou rekurzi s neúměrným nárokem na paměť počítače.Tuto situaci si Python sám ošetří tak, že po určitém počtu opakování výpočet zastaví.

V matematice známý pojem faktoriál čísla n neboli n faktoriál: (n!) je označení pro součin souvislé číselné řady 1 až n:
n! = n * (n-1) * (n-2) * ... *1   Ukážeme si jeho různé vyjádření:

Matematická definice:

0! = 1
n! = n(n-1)

Vyjádření pomocí iterace while...

def fact_w(n):
    f, i = 1, 0
    while i < n :
       i = i+1; f = f*i
    return f

Vyjádření pomocí iterace for...

def fact_f(n):
    f = 1
    for i in range(1, n+1):
	f = f*i
    return f

Vyjádření pomocí rekurze

def fact_r(n):
    if n == 0:             # základní případ (případně n < 2 )
        return 1
    return n * fact_r(n-1)

Opakovaný výpočet pomocí rekurze je někdy pomalejší než výpočet pomocí iterace. Na konci odstavce 13.2 si ukážeme výpočet Fibonacciho čísla rekurzí, iterací a rychlý výpočet pomocí memoizace.

Má se za to, že každé rekurzivní řešení lze vyjádřit iterační smyčkou a naopak. Oběma způsobům je společná existence mezní podmínky, určující konec opakovaného výpočtu.
Nekonečná rekurze může skončit krachem systému, zatímco nekonečná iterace je odchycena a ukončena Pythonem.


4.6 Iterace

Pro zvídavé

Iterace obecně je opakování určitého procesu v měnícím se kontextu. V prostředí Pythonu je iterace opakovaný výpočet pro jednotlivé členy iterovatelného objektu prostřednictvím iterátoru.

Iterovatelným objektem (iteráblem) jsou sekvence typu string, list, tuple, range, bytes, bytearray a kolekce typu dict, set, frozentset - rovněž objekty typu file a generátory.

Tyto objekty vlastní funkci iter(~) a metodu __iter__(), které umožňují vytvoření interního objektu, zvaného iterátor.

Iterátor je speciální 'kopie' iterovatelného objektu, disponující funkcí next(~) (a metodou __next__()), která postupně vrací své aktuálně dosažené prvky a vypouští je z 'kopie'. Vypuštění posledního elementu kopie je indikováno sdělením StopIteration.

>>> li = [2, 5, 0]            # iterable

>>> ili = iter(li)            # vytvoření iterátoru
>>> ili = li.__iter__()       # alternativní možnost

>>> next(ili)                 # první krok iterace
2
>>> ili.__next__()            # druhý krok iterace
5
>>> next(ili)                 # poslední krok iterace
0
>>> next(ili)       
StopIteration                 # info o konci iterace

Iterátor je v této chvíli prázdný. Opětovně použitelný iterátor vytvoříme opětovným použitím funkce iter(), případně metody  __iter__() :

>>> ili = li.__iter__()           

Vlastní iterátor si vytváří idiom FOR a funkce open(), min(), max(), map(), filter(), zip(), enumerate() a reversed().

Iterátory jsou rovněž iterovatelnými objekty (iterábly) ale nemají 'délku' a nelze je indexovat (nedisponují metodou __getitem__()). Jsou výhodné tím, že snižují spotřebu paměti; vyprázdněný iterátor je "garbage collected".

Generátory jsou iterátory, vytvořené generátorovou funkcí, případně generátorovým výrazem. Jsou popsány v kap.13.5, iterátory, definované třídou, jsou popsány v kap. 13.4.


4.7 Smyčka for...

for i in iterable: do something	

Smyčka for si pro zadaný iterovatelný objekt (iterable) vytvoří vlastní iterátor, s nímž provádí iteraci po prvcích objektu:

iter_obj = iter(iterable)         # vytvoření vlastního iterátoru 

while True:                          
    try:
        element = next(iter_obj)     
        # do something with element
    except StopIteration:            
        break                    # konec smyčky 

Funkce open("readme.txt") s vlastním iterátorem:

>>> f = open("c:/Abakus/readme.txt")      # iterátor pro readme.txt 
>>> next(f)                               # první řádek souboru
>>> next(f)                               # další řádek souboru
>>> for i in f: print(i, end=" ")         # zbývající řádky souboru

st = {3.6, "cat", True}                # kolekce typu set

for i in st:
    print(i, end=" ")
======== RESTART: F:/Codetest/HowTo/trampolina.py ========
True 3.6 cat 
>>>

Na výstupu idiomu FOR v konzole IDLE vidíme, že pořadí elementů se změnilo, protože kolekce (set) pořadí měnit může.

Iterace přes slovník (dict) vrací pouze klíče slovníku:

sl = {1: "uno", 2: "duo", 3: "tre"}      # kolekce typu dict

for i in sl:
    print(i, end=" ")
======== RESTART: F:/Codetest/HowTo/trampolina.py ========
1 2 3 
>>>

O tom, že naše kontejnery jsou vybaveny metodou __iter__ a že to tedy jsou iteráble, se přesvědčíme funkcí

>>> dir(zkoumaný_objekt)
jejímž výstupem je seznam metod a funkcí zadaného objektu, v němž metodu __iter__ nalezneme.


4.8 Funkce 'range'

Vestavěná funkce range(start, stop[, step]) vytvoří potenciální aritmetickou posloupnost od 0 po n-1, případně od m po n-1, případně od m po n-1 s krokem p. Argumenty start a step jsou nepovinné.
Slovo potenciální označuje tu skutečnost, že místo celé zadané řady čísel se při deklaraci uloží pouze její parametry a k vlastnímu vytvoření této posloupnosti dojde až při jejím volání. Jedná se o případ takzvaného odloženého (lazy) vytvoření iterovatelného objektu (nikoliv jeho iterátoru - viz. odst. 4.6).
Předností funkce range() je skutečnost, že zabírá stejné místo v paměti - bez ohledu na délku deklarované řady.

Tuto posloupnost lze použít jako argument při tvorbě prostého seznamu, entice, setu a sekvence bytes:

>>> list(range (7))              # chápáno jako range(0,7)
[0, 1, 2, 3, 4, 5, 6]
>>> tuple(range (2,7))
(2, 3, 4, 5, 6)
>>> set(range (0,7,2))
{0, 2, 4, 6}
>>> bytes(range (0,7,2))        
b'\x00\x02\x04\x06'
>>> list(range (7,5))            # bez vhodného kroku vždy prázdný
[]
>>> list(range (7,0,-3))         # vida
[7, 4, 1]

Objekt typu range je indexovaným (subscriptable) objektem. Jeho elementy jsou individuálně přístupné uvedením indexu v závorce a metodou __getitem__():

>>> range(7)[2]
2
>>> range(7).__getitem__(2)
2

Iterátor lze z objektu range vytvořit běžným způsobem funkcí iter(range) (range.__iter__() ) nebo smyčkou for..., která si iterátor vytvoří sama (sama si jej však také zkonzumuje). Iterace takovéhoto iterátoru je dychtivá (eager - viz  kap. 13.5)

>>> for i in range(7):                 eager iteration
...    print(i, end= ", ")
... 
0, 1, 2, 3, 4, 5, 6, >>>
for number in range(20):               eager iteration
    if number%3 == 0:
        print(number, end="  ")

Výstup v IDLE:

======== RESTART: F:/Codetest/HowTo/trampolina.py ========
0  3  6  9  12  15  18
>>>  

Poznámka: Takzvanou línou (lazy) iteraci lze provést prostřednictvím funkce range() v komprehenci entice - viz. kap. 8.10.


4.9 Funkce enumerate

Volání funkce enumerate(iterable, start=0) vrací objekt typu enumerate jenž je iterátorem, disponujícím metodou __next__() a funkcí next():

>>> fruits = ('banana', 'apple', 'pear', 'grape')      # iteráble
>>> enum = enumerate(fruits)                           # iterátor
>>> type(enum)                          # --> <class 'enumerate'>

Objekt typu enumerate není indexovatelný (není to iterábl), jeho elementy nejsou přímo přístupné prostřednictvím indexu v hranatých závorkách.

>>> enum[1]
# TypeError: 'enumerate' object is not subscriptable

Přístup k prvkům iterátoru lze realizovat postupně prostřednictvím iterační funkce next nebo smyčky for::

>>> next(enum)
(0, 'banana')
>>> enum.__next__()
(1, 'apple')

>>> for i in enum:
        print(i, end=" ")
(2, 'pear') (3, 'grape')                  # zbytek iterace	

Jak vidno, next(enum) i smyčka for vrací index a jemu příslušnou hodnotu. Index implicitně počíná nulou. Počáteční index lze změnit zadáním jiné hodnoty pro parametr start.

Funkci 'enumerate' lze použít pro vyjádření vztahu argument - upravený argument:

numbers = [2, 3, 4, 5]
for elem, value in enumerate(numbers, 1):       # změna hodnoty parametru
    print(elem, numbers[elem], " -> ", value**2)

Výstup v IDLE:

======== RESTART: F:/Codetest/HowTo/trampolina.py ========
1 3 -> 9
2 4 -> 16
3 5 -> 25
...
IndexError: list index out of range 

Naše malá záhada: Provedli jsme co jsme měli a přesto nám interpret hlásí chybu. Prosím laskavého čtenáře aby si zkusil sám nalézt příčinu.


4.10 Funkce filter, map a reduce

Všechny tyto tři funkce pracují s iterovatelnými objekty (iterábly - viz 4.6).

Funkce filter ( function or None, iterable ) vrací iterátor, jehož položky jsou filtrovány podle kritéria, zadaného funkcí z argumentu. Jako funkce se často používá anonymní funkce lambda.
Iteráblem může být objekt typu list, string, tuple, set, ...

Výsledný iterátor musíme vhodným způsobem rozbalit (*)

ages = [7, 10, 16, 18, 26, 35]
adults = filter(lambda x: x > 17, ages)

for x in adults:                      * zde idiomem 'for ...'
    print(x, end=" ")
	
* zde funkcí 'list'
not_adults = list(filter(lambda x: x <= 17, ages))	
18 24 32
>>> not_adults
[7, 10, 16]

Funkce map ( fce, iterable, ...) vrací iterátor, jenž aplikuje transformační funkci na každý element iteráblu (seznamu, entice, atp) a vrací výsledek. Iteráblů lze zadat více než jeden.

def squares(n):
  return n*n

numbers = (1, 2, 3, 4)
result = map(squares, numbers)
print(list(result))                        --> [1, 4, 9, 16]

Jiný příklad:

num1 = [4, 5, 6]
num2 = [5, 6, 7]

result = map(lambda x,y: x+y, num1, num2)
print(list(result))                        --> [9, 11, 13]

Funkce reduce ( fce, sequence [ , start ] ) vrací jedinou výslednou hodnotu z postupné aplikace dvou po sobě připravených hodnot. Tuto funkci nutno importovat z modulu functools.

from functools import reduce
 
def do_sum(x, y): 
    return x + y

print(reduce(do_sum, [1, 2, 3, 4]))               --> 10

Případně s funkcí lambda:
print(reduce(lambda x,y: x+y , range(1,5)))       --> 10

Funkce 'reduce' v tomto případě postupně provádí součty (((1+2)+3)+4.)


4.11 Funkce print()

Funkce print() se všemi svými parametry má tento tvar:

print(*objekty, sep="", end="\n", file=sys.stdout, flush=False)

Kdo si přečetl odstavec 3.4 Parametry a argumenty II, ví že parametr *objekty je sběrný enticový parametr a všechny ostatní parametry lze ignorovat, neboť to jsou parametry s počáteční hodnotou.
Takže se nám povinný tvar volání funkce smrskne na

print(*objekty)
přičemž i tento parametr lze vynechat a v tom případě nám funkce vytiskne prázdný řádek.

Funkce print vyvolá vyhodnocení jednotlivých argumentů v entici:

>>> print("Je mi", 12 + 9, "let.")
Je mi 21 let.                            # print odebral  "string"
>>>

Klíčové argumenty file=sys.stdout a flush=False zajišťují výstup tisku do okna konzoly.
Změnou argumentu end="\n" na end="" lze zajistit pokračování tisku na témže řádku, přičemž rozestupem uvozovek lze ovlivnit rozestup mezi jednotlivými hodnotami výstupu.
Změnou argumentu sep="" lze přikázat typ oddělovače, případně vzdálenost mezi prvky entice.

>>> print('a', 'b', 'c', 'd')
a b c d
>>> print('a', 'b', 'c', 'd', sep=' # ', end=' !!')
a # b # c # d !!>>>        # prompt '>>>' se vrací pouze v konzole

4.12 Interní index elementu

Všechny sekvence (viz kap. 2.3) jsou takzvaně "indexovatelné" (subscriptable), což znamená že vlastní metodu __getitem__(). Elementy těchto objektů jsou interně indexovány a pomocí těchto indexů jsou přímo dostupné závorkovým operátorem nebo prostřednictvím metody __getitem__():

>>> li = [2, 5, 0]           # 'subscriptable' objekt s indexy 0, 1, 2
>>> li[1]
5
>>> li.__getitem__(1)        # objektem zde je seznam (list)
5

Názornou ilustraci indexování u řetězce představuje tento obrázek:

Poznámka: Grafická interpretace indexování, použitá u tohoto obrázku, se liší od interpretace, použité u obrázku v kap. 6.1. tím, že zde je za indexované místo považován prostor před, mezi a za posledním znakem řetězce, zatímco na obrázku v kap. 6.1 je za indexem označené místo považována přesně pozice znaku. Interpretace v kap. 6.1 je pro naši potřebu vhodnější.

Pomocí záporných čísel se provádí indexování zprava doleva:

>>> fruit[-1]
'a'
>>> fruit[-6]
'b'
>>> fruit[6]
IndexError: string index out of range

Metodu __getitem__() vlastní také objekt typu dict. Jeho elementy jsou podobně přístupné - s tím rozdílem, že jako indexu nutno použít klíč slovníku:

>>> dc = {"m": 5, "n": 6}    # 'subscriptable' objekt s klíči "m", "n"
>>> dc["m"]
5
>>> dc.__getitem__("n")
6

Iterátory objektů (odst. 4.6), přesto, že jsou rovněž iterovatelné, nejsou 'subscriptable' - nepoužívají indexy.


4.13 Glosář

podmíněný příkaz (conditional statement)
Příkaz, který řídí tok výpočtu v závislosti na nějaké podmínce. V Pythonu se pro podmíněné příkazy používají klíčová slova if, elif a   else.
podmínka (condition)
Booleovský výraz v podmíněném výrazu, který rozhoduje o tom, která větev se provede.
řetězená podmínka (chained conditional)
Podmíněné větvení s více než dvěma toky výpočtu. V Pythonu se řetězené podmínky píší pomocí příkazů if ... elif ... else.
větev (branch)
Jedna z možných cest výpočtu určená vyhodnocením podmínky.
iterace (iteration)
Opakované provádění sady programových příkazů
smyčka (loop)
Příkaz nebo skupina příkazů, které se provádějí opakovaně, dokud není splněna ukončující podmínka.
nekonečná smyčka (infinite loop)
Smyčka, ve které ukončující podmínka není nikdy splněna.
proměnná smyčky (loop variable)
Proměnná, jejíž hodnota se mění po každém provedení smyčky.
počítadlo (counter)
Proměnná pro počítání něčeho; obvykle nastavená s nulovou počáteční hodnotou a navyšovaná v těle smyčky.
tělo (body)
Příkazy uvnitř smyčky nebo funkce

4.14 Cvičení

Následující příklady zapisujte do skriptů v IDLE s názvem příslušné funkce. Výstupy spuštěných skriptů se budou postupně realizovat v okně Python Shell.
Všechny příklady zapisujte do samostatných souborů ve složce Kap-04.

Příklady s doctestem budou mít na konci skriptu tento kód:

if __name__ == '__main__':
    import doctest
    doctest.testmod()

Tyto příklady řešte až po prostudování textu v kap. 5.11. Při řešení geometrických úloh pomůže tento vlídný text .

  1. Napište funkci compare(a,b), která vrací 1 pro a>b, 0 pro a==b a -1 pro a<b.
    def compare (a, b):
        """
        >>> compare(5,4)
        1
        >>> compare(7,7)
        0
        >>> compare(2,3)
        -1
        """
        # Zde napište tělo funkce
    
  2. Použijte přírůstkový rozvoj k vytvoření funkce hypotenuse, která vrací délku přepony pravoúhlého trojúhelníka pro zadané délky odvěsen.
    Přírůstkové kroky si zkoušejte v samostatné konzole Pythonu, nikoliv v konzole z IDLE. Editační okno a jemu příslušná konzola jsou ovšem z IDLE.
    def hypotenuse (a,b):
        """
        >>> hypotenuse(3,4)
        5.0
        >>> hypotenuse(12,5)
        13.0
        >>> hypotenuse(7,24)
        25.0
        """
        # tělo funkce může mít pouhé 2 řádky
    
  3. Napište funkci slope(x1,y1,x2,y2), která vrací tangent úhlu (sklonu) přímky procházející body (x1,y1) a (x2,y2). Funkce musí vyhovět následujícím testům:
    def slope (x1,y1,x2,y2):
        """
        >>> slope(5,3,4,2)
        1.0
        >>> slope(1,2,3,2)
        0.0
        >>> slope(1,4,1,2)         
        kolmice k ose 'x'           Ošetřená výjimka!
        >>> slope(2,4,1,2)
        2.0
        """
        # Zde napište tělo funkce
    
  4. Napište funkci intercept(x1,y1,x2,y2), která vrací ypsilonovou pořadnici průsečíku přímky s osou y (pro x=0). Použijte rovnici přímky, procházející 2 body.

    def intercept (x1,y1,x2,y2):
        """
        >>> intercept(1,6,3,12)
        3.0
        >>> intercept(6,1,1,6)
        7.0
        >>> intercept(4,6,12,8)
        5.0
        """
        # Zde napište tělo funkce
    
  5. Napište funkci is_multiple(m,n), která vrátí True, je-li m násobkem n a False, není-li.
    def is_multiple( (m,n):
        """
        >>> is_multiple(12,3)
        True
        >>> is_multiple(12,4)
        True
        >>> is_multiple(12,5)
        False
        """
        # Zde napište tělo funkce
    
  6. Napište fci is_divisible(m,n), která přijme celá čísla jako argument a podle situace vytiskne True nebo False.

    def is_divisible( (m,n):
        """
        >>> is_divisible(20,4)
        True
        >>> is_divisible(21,8)
        False
        """
        # Zde napište tělo funkce
    

    Při řešení použijete podmínky if ... :, else: a vyberete si jeden z existujících způsobů dělení: normální a/b, celočíselné a//b nebo dělení se zbytkem (modulo) a%b.

  7. Napište tělo funkce fah2cel(t), která převede teplotu ve stupních Fahrenheitových na stupně Celsiovy a vrátí ji jako celé číslo. Použijete vestavěnou fci round(n). Informaci o této funkci získáte zadáním >>> round.__doc__ v konzole Pythonu.
    def fah2cel(t):
        """
        >>> fah2cel(212)
        100
        >>> fah2cel(32)
        0
        >>> fah2cel(-40)
        -40
        >>> fah2cel(37)
        3
        """
        # Zde napište tělo funkce
    
  8. Napište funkci cels2fah(t), která převede teplotu ve stupních Celsiových na stupně Fahrenheitovy.

comment up next how to end end