<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xml" href="/cjs/screen.xsl" media="screen"?>
<lecture>

<meta>
  <maintitle>Python</maintitle>
  <author>Jiří Znamenáček</author>
  <title>Úvod do Python'u</title>
  <date>2011-02-17</date>
  <link><!--a href="http://vyuka.ookami.cz" rel="external">http://vyuka.ookami.cz</a--></link>
</meta>


<slide title="Historie Pythonu">
  
  <img src="_files/logo_[zirael.org].png" width="113" height="99" alt="" title="Python @ zirael.org" align="left"/>
  <img src="_files/python-logo.gif" width="211" height="71" alt="" title="python.org" align="right"/>
  <br clear="all"/>
  <ul>
    <li>Guido van Rossum (BDFL), přelom 80. a 90. let, následovník jazyka ABC</li>
    <li>16. 10. 2000 – verze 2.0 (komunitní vývoj, <i>full garbage collector</i>, prvotní podpora pro Unicode...)</li>
    <li>3. 12. 2008 – verze 3.0, záměrně první zpětně nekompatibilní (skutečná podpora Unicode'u, sjednocení syntaxe a „vnitřností“, vyčištění systémové knihovny...)</li>
  </ul>
  <p>Řada 2.x tu bude ještě dlouho<sup>*</sup>, řada 3.x je ale v mnoha ohledech „hezčí“ jazyk.</p>
  <note><sup>*</sup> Především kvůli externím knihovnám. Nicméně od ledna 2020 už by neměla býti oficiálně udržována.</note>
  <p>Na druhou stranu je třeba přiznat, že trojková řada prošla dosti překotným vývojem a vlastně až verze Python'u 3.2 se dá pokládat za stabilní a rozumně použitelnou.</p>
  <note>A podle samotných vývojářů jazyka až verze 3.6 je rychlejší než 2.7…</note>
  <handout>
    historie Pythonu, jméno, logo, evoluce 2.x-&gt;3.x
    http://en.wikipedia.org/wiki/Python_(programming_language)
    http://docs.python.org/3.1/license.html
    http://www.python.org/psf/
    Benevolent Dictator for Life (BDFL)
  </handout>

</slide>
<slide title="Python 2.x versus Python 3.x">
  
  <ul _class="incremental">
    <li>
      nejviditelnější změna
      <example lang="python">
        print 'Ahoj, Karle!'    # Python 2.x
        print('Ahoj, Karle!')   # Python 3.x
      </example>
    </li>
    <li>
      nejdůkladnější změna
      <example lang="python">
        u"Ahoj, světe!"   # Python 2.x
        "Ahoj, světe!"    # Python 3.x
      </example>
    </li>
    <li>
      sjednocení syntaxe a „vnitřností“ (větší důraz na iterátory...)
    </li>
    <li>
      vyčištění systémové knihovny (včetně přesunu části funkcí z globálního jmenného prostoru)
    </li>
    <li>
      atd.
    </li>
  </ul>
  <handout>
    <a class="external" href="http://python.org/doc/3.0.1/whatsnew/3.0.html">http://python.org/doc/3.0.1/whatsnew/3.0.html</a>
    <br/>
    <a class="external" href="http://python.org/doc/3.0.1/tutorial/index.html">http://python.org/doc/3.0.1/tutorial/index.html</a>
  </handout>

</slide>
<slide title="Užitečné odkazy">
  
  <ul>
    <li><a class="external" href="http://python.org">http://python.org</a> – hlavní web jazyka Python</li>
    <li><a class="external" href="http://docs.python.org">http://docs.python.org</a> – on-line dokumentace ke všem verzím jazyka Python</li>
    <!--li><a class="external" href="http://downloads.ActiveState.com">http://downloads.ActiveState.com</a></li-->
  </ul>
  <br/>
  <ul>
    <!--
      http://cheeseshop.python.org/pypi
      http://pypi.python.org
    -->
    <li><a class="external" href="http://pypi.org">http://pypi.org</a> – „vrchní centrála“ pro pythoní balíčky</li>
    <li><a class="external" href="http://code.activestate.com/recipes/langs/python/">http://code.activestate.com/recipes/langs/python/</a> – spousta užitečných pythoních kódů</li>
  </ul>
  <br/>
  <ul>
    <!--li><a class="external" href="http://DiveIntoPython3.net">http://DiveIntoPython3.net</a></li-->
    <li><a class="external" href="http://DiveIntoPython3.py.cz">http://DiveIntoPython3.py.cz</a> – český překlad jedné z nejlepších knih o Python'u</li>
    <!--li><a class="external" href="http://DiveIntoPython.net">http://DiveIntoPython.net</a></li-->
  </ul>
  <br/>
  <ul>
    <li><a class="external" href="http://DreamPie.org">http://DreamPie.org</a> – bezvadný interaktivní editor (mimo jiné obsahuje víceřádkovou historii)</li>
  </ul>
  <handout>
    http://wiki.python.org/moin/BeginnersGuide/Programmers
  </handout>

</slide>
<slide title="Charakter jazyka">
  
  <p>Python je:</p>
  <ul>
    <li>
      interpretovaný, dynamicky typovaný vysokoúrovňový jazyk
    </li>
    <li>
      procedurální, ale i objektový a dokonce i funkcionální
    </li>
    <li>
      funkce mají výjimečné postavení, jsou zde i uzávěry (<em>closures</em>)
    </li>
    <li>
      ošetření havarijních situací výjimkami
    </li>
  </ul>
  <p>Dále též:</p>
  <ul>
    <li>
      všechno v Pythonu je objekt, navíc dokonce „first-class object“ (tj. je možné cokoliv předat jako argument do funkce; tedy samozřejmě třeba i jinou funkci!)
      <example lang="python">"Ahoj, světe!".split()</example>
    </li>
    <li>
      proměnné se nedeklarují, rovnou se jim přiřazuje hodnota (ale dosud nepoužitou proměnnou nemůžete „zavolat“, dostali byste <code>NameException</code>)
    </li>
    <li>
      původně existovalo velmi striktní rozlišení mezi příkazy a výrazy (ale zavedení ternárního výrazu to dost nabouralo; škoda že není výrazem aspoň přiřazení…)
      <note>Světe div se, od Python'u 3.8 budeme mít k dispozici <a href="https://docs.python.org/3.8/whatsnew/3.8.html#assignment-expressions" class="external"><em>assignment expressions</em></a>.</note>
    </li>
    <li>
      case-sensitive (a má odpovídající konvence na psaní názvů jednotlivých typů objektů)<br/>
      <code>joined_lower</code> - funkce &amp; metody &amp; atributy,
      <code>ALL_CAPS</code> - konstanty,
      <code>StudlyCaps</code> - třídy
    </li>
  </ul>
  <p>Jinými slovy je Python elegantní jazyk na zápis algoritmů. Ale nečekejte, že by zároveň byl i nějakým přeborníkem ve sprintu, od toho jsou tu jazyky jiné.</p>
  <handout>
    ~ "All names in Python are case-sensitive: variable names, function names, class names, module names, exception names. If you can get it, set it, call it, construct it, import it, or raise it, it’s case-sensitive."
    ~ všechno v Pythonu je „first-class object“ - je možné cokoliv předat jako argument do funkce
      "This is important, so I’m going to repeat it in case you missed it the first few times: everything in Python is an object. Strings are objects. Lists are objects. Functions are objects. Classes are objects. Class instances are objects. Even modules are objects."
  </handout>

</slide>
<slide title="Ukázka – „QuickSort“">

  <example lang="python">
def qs(a):
    if a == []:
        return []
    else:
        pivot = a[0]
        left  = [x for x in a     if x &lt;  pivot]
        right = [x for x in a[1:] if x >= pivot]
        return qs(left) + [pivot] + qs(right) 
  </example>
  <handout>
    Odsazení jednotlivých částí do bloků je zcela zásadní!
  </handout>

</slide>
<slide title="Ukázka – „dataclasses“">

  <p>Potřebujete-li vytvořit datovou třídu:</p>
  <example lang="python">
from dataclasses import make_dataclass

Point = make_dataclass('Point', ['x', 'y', 'z'])

p = Point(1.5, 2.5, 3.0)
print(p)    # Point(x=1.5, y=2.5, z=3.0)
  </example>

  <p>Pokud musíte zaznamenat i typy nebo dodat k uložení funkcionalitu navíc:</p>
  <example lang="python">
from dataclasses import dataclass

@dataclass
class Point:
    x: float
    y: float
    z: float = 0.0

p = Point(1.5, 2.5)
print(p)    # Point(x=1.5, y=2.5, z=0.0)
  </example>

<!--
  <p>Klasicky (a bez typů):</p>
  <example lang="python">
class Point:
    def __init__(self, x, y, z=0.0):
        self.x = x
        self.y = y
        self.z = z

p = Point(1.5, 2.5)
print(p)    # Point(x=1.5, y=2.5, z=0.0)
print(p.x, p.y, p.z)    # 1.5 2.5 0.0
  </example>
-->

</slide>
<slide title="Poznámka ke kódování">
  
  <example lang="python">
      # -*- coding: utf-8 -*-
      # encoding: utf-8
  </example>
  <ul>
    <!--li>v historicky dávné době byl Python asi čistě ASCII (nevím, nezažil :)</li-->
    <li>
      v Pythonu 2.x se dá určit kódování souboru, ale řetězce jsou brány jako sekvence osmibitových znaků
      <example lang="python">
        "ASCII string"    # Python 3.x
        u"Ahoj, světe!"   # Python 2.x
      </example>
    </li>
    <li>
      až v Pythonu 3.x je konečně všechno nativně UTF-8 (a to dokonce až na úroveň názvů proměnných či funkcí; bohužel s výjimkou výchozího kódování souborových proudů)
      <example lang="python">
        "Ahoj, světe!"   # textový řetězec v kódování UTF-8
        b"bytes"         # sekvence bajtů
      </example>
      <note>
        PS: Od Python'u 3.7 si ale můžete vynutit mód „UTF-8 všude“ vhodným nastavením proměnných prostředí a podobně.
      </note>
    </li>
  </ul>
  <p>Ale spousta nástrojů s tím pořád ještě nepočítá...</p>
  <handout>
    ~ Python a kódování modulu/souboru (od Python 3.x je defaultně předpokládáno UTF-8, jiné se musí uvést, stejně jako pro Python 2.x)
      http://docs.python.org/dev/3.0/howto/unicode.html
  </handout>

</slide>
<slide title="Klíčová slova">
  
  <p>
    Programovací jazyk má svůj charakter podle toho, jaké obsahuje základní typy a jaké nástroje pro jejich použití nabízí. Postupně se seznámíme s obojím, ale začneme od klíčových slov:
  </p>
  <!--
Python 3.4.3
>>> from keyword import kwlist
>>> kwlist
['False', 'None', 'True', 'and', 'as', 'assert', 'break', 'class', 'continue', 'def', 'del', 'elif', 'else', 'except', 'finally', 'for', 'from', 'global', 'if', 'import', 'in', 'is', 'lambda', 'nonlocal', 'not', 'or', 'pass', 'raise', 'return', 'try', 'while', 'with', 'yield']

Python 3.7.4 (35 slov)
>>> from keyword import kwlist
>>> kwlist
['False', 'None', 'True', 'and', 'as', 'assert', 'async', 'await', 'break', 'class', 'continue', 'def', 'del', 'elif', 'else', 'except', 'finally', 'for', 'from', 'global', 'if', 'import', 'in', 'is', 'lambda', 'nonlocal', 'not', 'or', 'pass', 'raise', 'return', 'try', 'while', 'with', 'yield']
  -->
  <example lang="python">
    False          await              else             import           pass
    None           break              except           in               raise
    True           class              finally          is               return
    and            continue           for              lambda           try
    as             def                from             nonlocal         while
    assert         del                global           not              with
    async          elif               if               or               yield
  </example>
  <note>
    Dá se předpokládat, že s výjimkou <code>yield</code> (a možná i <code>lambda</code>, <code>nonlocal</code> nebo <code>as</code>) budete všechno již nějak znát.
  </note>

</slide>
<slide title="Vestavěné funkce">
  
  <!--
Například [x for x in dir(__builtins__) if callable(getattr(__builtins__, x))] v "Python 3.4.3":
['ArithmeticError', 'AssertionError', 'AttributeError', 'BaseException', 'BlockingIOError', 'BrokenPipeError', 'BufferError', 'BytesWarning', 'ChildProcessError', 'ConnectionAbortedError', 'ConnectionError', 'ConnectionRefusedError', 'ConnectionResetError', 'DeprecationWarning', 'EOFError', 'EnvironmentError', 'Exception', 'FileExistsError', 'FileNotFoundError', 'FloatingPointError', 'FutureWarning', 'GeneratorExit', 'IOError', 'ImportError', 'ImportWarning', 'IndentationError', 'IndexError', 'InterruptedError', 'IsADirectoryError', 'KeyError', 'KeyboardInterrupt', 'LookupError', 'MemoryError', 'NameError', 'NotADirectoryError', 'NotImplementedError', 'OSError', 'OverflowError', 'PendingDeprecationWarning', 'PermissionError', 'ProcessLookupError', 'ReferenceError', 'ResourceWarning', 'RuntimeError', 'RuntimeWarning', 'StopIteration', 'SyntaxError', 'SyntaxWarning', 'SystemError', 'SystemExit', 'TabError', 'TimeoutError', 'TypeError', 'UnboundLocalError', 'UnicodeDecodeError', 'UnicodeEncodeError', 'UnicodeError', 'UnicodeTranslateError', 'UnicodeWarning', 'UserWarning', 'ValueError', 'Warning', 'ZeroDivisionError', '__build_class__', '__import__', '__loader__', 'abs', 'all', 'any', 'ascii', 'bin', 'bool', 'bytearray', 'bytes', 'callable', 'chr', 'classmethod', 'compile', 'complex', 'copyright', 'credits', 'delattr', 'dict', 'dir', 'divmod', 'enumerate', 'eval', 'exec', 'exit', 'filter', 'float', 'format', 'frozenset', 'getattr', 'globals', 'hasattr', 'hash', 'help', 'hex', 'id', 'input', 'int', 'isinstance', 'issubclass', 'iter', 'len', 'license', 'list', 'locals', 'map', 'max', 'memoryview', 'min', 'next', 'object', 'oct', 'open', 'ord', 'pow', 'print', 'property', 'quit', 'range', 'repr', 'reversed', 'round', 'set', 'setattr', 'slice', 'sorted', 'staticmethod', 'str', 'sum', 'super', 'tuple', 'type', 'vars', 'zip']

Python 3.7.4 (142 objektů)
[x for x in dir(__builtins__) if callable(getattr(__builtins__, x))]
['ArithmeticError', 'AssertionError', 'AttributeError', 'BaseException', 'BlockingIOError', 'BrokenPipeError', 'BufferError', 'BytesWarning', 'ChildProcessError', 'ConnectionAbortedError', 'ConnectionError', 'ConnectionRefusedError', 'ConnectionResetError', 'DeprecationWarning', 'EOFError', 'EnvironmentError', 'Exception', 'FileExistsError', 'FileNotFoundError', 'FloatingPointError', 'FutureWarning', 'GeneratorExit', 'IOError', 'ImportError', 'ImportWarning', 'IndentationError', 'IndexError', 'InterruptedError', 'IsADirectoryError', 'KeyError', 'KeyboardInterrupt', 'LookupError', 'MemoryError', 'ModuleNotFoundError', 'NameError', 'NotADirectoryError', 'NotImplementedError', 'OSError', 'OverflowError', 'PendingDeprecationWarning', 'PermissionError', 'ProcessLookupError', 'RecursionError', 'ReferenceError', 'ResourceWarning', 'RuntimeError', 'RuntimeWarning', 'StopAsyncIteration', 'StopIteration', 'SyntaxError', 'SyntaxWarning', 'SystemError', 'SystemExit', 'TabError', 'TimeoutError', 'TypeError', 'UnboundLocalError', 'UnicodeDecodeError', 'UnicodeEncodeError', 'UnicodeError', 'UnicodeTranslateError', 'UnicodeWarning', 'UserWarning', 'ValueError', 'Warning', 'ZeroDivisionError', '__build_class__', '__import__', '__loader__', 'abs', 'all', 'any', 'ascii', 'bin', 'bool', 'breakpoint', 'bytearray', 'bytes', 'callable', 'chr', 'classmethod', 'compile', 'complex', 'copyright', 'credits', 'delattr', 'dict', 'dir', 'divmod', 'enumerate', 'eval', 'exec', 'exit', 'filter', 'float', 'format', 'frozenset', 'getattr', 'globals', 'hasattr', 'hash', 'help', 'hex', 'id', 'input', 'int', 'isinstance', 'issubclass', 'iter', 'len', 'license', 'list', 'locals', 'map', 'max', 'memoryview', 'min', 'next', 'object', 'oct', 'open', 'ord', 'pow', 'print', 'property', 'quit', 'range', 'repr', 'reversed', 'round', 'set', 'setattr', 'slice', 'sorted', 'staticmethod', 'str', 'sum', 'super', 'tuple', 'type', 'vars', 'zip']
  -->
  <example lang="python">
abs()             divmod()        int()             print()         vars()
all()             enumerate()     isinstance()      property()      zip()
any()             eval()          issubclass()      quit()
ascii()           exec()          iter()            range()
bin()             exit()          len()             repr()
bool()            filter()        list()            reversed()
breakpoint()      float()         locals()          round()
bytearray()       format()        map()             set()
bytes()           frozenset()     max()             setattr()
callable()        getattr()       memoryview()      slice()
chr()             globals()       min()             sorted()
classmethod()     hasattr()       next()            staticmethod()
compile()         hash()          object()          str()
complex()         help()          oct()             sum()
delattr()         hex()           open()            super()
dict()            id()            ord()             tuple()
dir()             input()         pow()             type()
  </example>
  <p>
    Bohužel – jak můžete vidět – „čištění“ Python'u do trojkové verze nebylo tak důkladné, jak mělo být (a to se týká nejen vestavěných funkcí a jejich rozložení na globální úrovni a v modulech).
  </p>

</slide>
<slide title="Standardní knihovna">
  
  <p>
    Kromě toho nabízí Python obsáhlou standardní knihovnu. Najdeme v ní například moduly pro:
  </p>
  <ul>
    <li>práci s reálnými čísly v libovolné přesnosti</li>
    <li>generování náhodných čísel</li>
    <li>práci s datem</li>
    <li>operace nad souborovým systémem (včetně knihovny pro práci s dočasnými soubory)</li>
    <li>rozhraní pro databázi SQLite3 (která je součástí distribuce)</li>
    <li>práci s komprimovanými a některými textovými a grafickými formáty</li>
    <li>obsluhu mailboxu</li>
    <li>parsování XML</li>
    <li>jednoduchý webserver</li>
    <li>GUI založené na Tk (v posledních verzích Python'u už obsahuje i grafická témata)</li>
    <li>„odbroukovávání“ kódu</li>
  </ul>

</slide>
<slide title="„help()“ – nápověda">

  <p>
    Nejlepší je samozřejmě používat nějakou externí nápovědu nebo alespoň nápovědu, kterou nám poskytuje nějaké vývojové prostředí přímo při psaní kódu. Občas se nám však může stát, že jsme omezeni na příkazovou řádku (např. při vzdáleném přístupu na server), a pak budeme rádi, že Python má k dispozici nápovědu i v takovém případě.
  </p>
  <p>
    Jádrem této pythonovské <strong>nápovědy</strong> je funkce <code>help()</code>. Je pochopitelně zamýšlena pro použití v rámci interaktivní konzole a je možno ji použít třemi rozdílnými způsoby:
  </p>
  
  <p class="enumerate">
    Zavolání funkce <em>help()</em> bez parametrů přepne interaktivní konzoli – se standardní výzvou <code>&gt;&gt;&gt;</code> – do <em>módu nápovědy</em>, který se hlásí vlastní výzvou <code>help&gt;</code> a reaguje na příkazy nápovědy:
  </p>
  <example lang="python">
>>> help()

Welcome to Python 3.2!  This is the online help utility.

If this is your first time using Python, you should definitely check out
the tutorial on the Internet at http://docs.python.org/tutorial/.

Enter the name of any module, keyword, or topic to get help on writing
Python programs and using Python modules.  To quit this help utility and
return to the interpreter, just type "quit".

To get a list of available modules, keywords, or topics, type "modules",
"keywords", or "topics".  Each module also comes with a one-line summary
of what it does; to list the modules whose summaries contain a given word
such as "spam", type "modules spam".

help>
  </example>
  <p>
    V tomto módu se můžete přímo ptát na konkrétní prvky jazyka (zkuste napsat např. <em>for</em>), zabudované moduly (zkuste třeba <em>math</em>) a podobně. Zpět do interpretru se vrátíte příkazem <code>quit</code> (bez závorek!).
  </p>
  
  <p class="enumerate">
    Na vlastnosti konkrétního objektu se můžete zeptat přímo v interpretru pomocí volání <code>help(OBJEKT)</code>:
  </p>
  <example lang="python">
>>> import math
>>> help(math)
Help on built-in module math:
... # vynechaná spousta textu
  </example>
  
  <p class="enumerate">
    Podobně zavoláním <code>help('dotaz')</code> se vám dostane stejného výstupu, jako kdybyste v <em>módu nápovědy</em> (tedy s výzvou <code>help&gt;</code> napsali přímo <code>dotaz</code>)
  </p>
  <example lang="python">
>>> help('for')
The ``for`` statement
... # vynechaná spousta textu
  </example>

</slide>
<slide title="Komentáře &amp; dokumentační řetězce">

  <p>
    <em>Dokumentační řetězce</em> jsou obyčejné pythoní řetězce na první řádce příslušného <em>bloku jmenného prostoru</em><sup>*</sup>, tedy například hned na začátku těla funkce:
  </p>
  
  <example lang="python">
  # funkce pro zpracování vstupního čísla
  def fnce(číslo):
    """
    Funkce fnce() očekává na vstupu právě jedno číslo.
    Na svém výstupu vrací toto číslo prohnané modulem zpracovator.
    """
    import zpracovator
    n = zpracovator.zpracuj()
    return n
  </example>
  <notes>
    <note>
      <em>docstring</em> : jak kód používat
    </note>
    <note>
      <em>comment</em> : jak a proč daný kód funguje (je napsán)
    </note>
  </notes>
  <handout>
    ~ "Docstrings = How to use code   |   Comments = Why (rationale) &amp; how code works"
  </handout>
  
  <p>
    Zatímco <em>komentáře</em> jsou ve zdrojovém kódu pouze pro potřeby programátora, <em>dokumentační řetězce</em> jsou plnoprávnou částí kódu. Dokonce tak moc, že nahradí BLOK výkonného kódu a že jsou programově přístupné za běhu programu!
  </p>
  <note>
    Viz „magický“ objekt <code>__doc__</code>.
  </note>
  <p>
    PS: Mimochodem – dokumentační řetězce stojí za většinou „magie“ vestavěné nápovědy, tj. za chováním funkce <em>help()</em>.
  </p>
  <note>
    <sup>*</sup> Kromě prvního řádku těla funkce jsou dalšími možnými umístěními dokumentačních řetězců první řádek těla třídy (tedy hned po <code>class TŘÍDA:</code>) a první řádek modulu (tedy každého skriptu; samozřejmě až po případných řídicích hlavičkách interpretru a kódování). Jako dokumentační řetězec je přitom brán jakýkoli pythoní řetězec, tedy i jednořádkový v jednoduchých uvozovkách či apostrofech, byť samozřejmě víceřádková varianta je výrazně převažující (kvůli nápovědě a především pak kvůli <a href="?slajd=13"><em>doctestům</em></a>).
  </note>

</slide>
<slide title="Dokumentační testy">

  <p>
    Dokumentační řetězce mají mimochodem ještě jedno velmi šikovné využití – pokud do nich napíšete volání dané funkce jako na příkazové řádce, můžete na uvedený kód (a tudíž i implementaci) později zavolat tzv. <em>dokumentační test</em>:
  </p>
  <example lang="python">
#!/usr/bin/env python3

def funkce():
    '''Tato funkce vždy vrací 666.
    >>> funkce()
    333
    '''
    return 666
  </example>
  <br/>
  <example lang="bash">
$ python -m doctest docs.py 
**********************************************************************
File "docs.py", line 6, in docs.funkce
Failed example:
    funkce()
Expected:
    333
Got:
    666
**********************************************************************
1 items had failures:
   1 of   1 in docs.funkce
***Test Failed*** 1 failures.
  </example>

</slide>
<slide title="Příkaz „pass“">

  <p>
    Podobnou funkci jako <em>dokumentační řetězce</em> zastává také příkaz <code>pass</code>. Jedná se o jakousi NOP-instrukci – uvedený příkaz je platný, případný jím vytvořený blok je validní částí kódu, jen prostě nic nedělá:
  </p>
  <example src="_files/pass.4.py" lang="python" />
  <p>
    Použití nachází všude tam, kde je očekáván kód, ale buď nemá nic dělat nebo ho teprve časem dopíšeme.
  </p>
  <note>
    Nejtypičtější použití je asi u definic minimálních tříd nebo přípravu jejich metod:
    <example lang="python">
      class MojeTřída:
        pass
    </example>
  </note>

</slide>
<slide title="Příkaz „...“">

    <p>
      Světe div se, ale zadat prázdný nic nedělající příkaz se dá ještě jedním a snad ještě výmluvnějším způsobem, totiž pomocí objektu tzv. <em>výpůstky</em> <code>...</code>:
    </p>
    <example lang="python">
      class MojeTřída:
        ...
    </example>
    <p>
      Tohle je skutečně validní kód! A každému je jasné, že tu asi chybí implementace třídy ^_~ Jinak se ovšem výpůstky (aneb <em>Ellipsis</em>) používají snad jenom u <a href="/materialy/python/numpy/slices.xml?slajd=5">vynechávaných os v <em>NumPy</em></a>.
    </p>

</slide>
<slide title="Datové typy">
  
  <table width="80%" align="center" border="1" cellspacing="0" frame="border" rules="groups">
    <col align="center" />
    <col align="center" />
    <col align="left" style="border-left: 1px solid black; font-style: italic;" />
    <thead>
      <tr>
        <th>proměnné (<i>mutable</i>)</th>
        <th>neproměnné (<i>immutable</i>)</th>
        <th>typ</th>
      </tr>
    </thead>
    <tbody>
      <tr align="center">
        <td>—</td>
        <td><code>int()</code></td>
        <td>číselný</td>
      </tr>
      <tr align="center">
        <td>—</td>
        <td><code>float()</code></td>
        <td>číselný</td>
      </tr>
      <tr align="center">
        <td>—</td>
        <td><code>complex()</code></td>
        <td>číselný</td>
      </tr>
      <tr align="center">
        <td>—</td>
        <td><code>str()</code>, <code>''</code>, <code>""</code></td>
        <td>sekvenční</td>
      </tr>
      <tr align="center">
        <td><code>bytearray()</code></td>
        <td><code>bytes()</code>, <code>b''</code>, <code>b""</code></td>
        <td>sekvenční</td>
      </tr>
      <tr align="center">
        <td><code>list()</code>, <code>[]</code></td>
        <td><code>tuple()</code>, <code>()</code>, <code>,</code></td>
        <td>sekvenční</td>
      </tr>
      <tr align="center">
        <td>—</td>
        <td><code>range()</code></td>
        <td>sekvenční</td>
      </tr>
      <tr align="center">
        <td><code>set()</code></td>
        <td><code>frozenset()</code></td>
        <td>množinový</td>
      </tr>
      <tr align="center">
        <td><code>dict()</code>, <code>{}</code></td>
        <td>—</td>
        <td>mapovací</td>
      </tr>
    </tbody>
  </table>
  <br/>
  <note>
    Uvedené funkce slouží zároveň jako konstruktory příslušných prázdných typů.
  </note>
  
  <handout>
    Číselné typy se berou také jako immutable.
  </handout>

</slide>
<slide title="Datové typy – příklady">
  
  <ul>
    <li><strong>Boolean</strong> – <code>True</code>, <code>False</code></li>
    <li><strong>Number</strong> – <code>1</code>, <code>2.3</code>, <code>4/5</code>, <code>2+3j</code></li>
    <li><strong>String</strong> – <code>"Ahoj, světe!"</code></li>
    <li><strong>Byte</strong> – <code>b"\x89PNG\r\n\x1a\n"</code></li>
    <li><strong>List</strong> – <code>[2, 'a', {},]</code></li>
    <li><strong>Tuple</strong> – <code>(2, 'a', {},)</code></li>
    <li><strong>Set</strong> – <code>{2, 'a', {},}</code></li>
    <li><strong>Dictionary</strong> – <code>{ 'jmeno': ('Karel', 'Novák'), 'vek': 23, }</code></li>
  </ul>
  <handout>
    ~ Programovací jazyk má svůj charakter podle toho, jaké obsahuje základní typy a jaké nástroje pro jejich použití nabízí.
  </handout>

</slide>
<slide title="Operátory">
  
  <ul>
    <li>číselné: <code>+   -   *   **   /   //   %</code></li>
    <li>logické: <code>and</code>   <code>or</code>   <code>not</code></li>
    <li>porovnávací: <code>&lt;   &gt;   ==   !=   &lt;=   &gt;=</code></li>
    <li>bitové: <code>&lt;&lt;   &gt;&gt;   &amp;   |   ^   ~</code></li>
    <li>speciální: <code>in</code> , <code>not in</code> ; <code>is</code> , <code>is not</code></li>
  </ul>
  <p>
    Občas je možné si výraz zkrátit: <code>a = a + 3</code> je prakticky totéž jako <code>a += 3</code>
  </p>
  <note>
    Tedy skoro ve všech případech. Interně se na každý z operátorů totiž volá jiná „magická“ metoda, jen je často <code>+=</code> namapována na stejnou jako pro <code>+</code>. Ale není to pravda u všech typů!
  </note>
  <p>
    Pozor na priority (a typy porovnávaných objektů)! Už z důvodu čitelnosti je lepší závorkovat.
  </p>
  <handout>
  # left-shift, right-shift, AND, OR, XOR, invert
  </handout>

</slide>
<slide title="Příklady – čísla">

  <example lang="python">
>>> a = 5
>>> b = 3
>>> a + b
8
>>> type(5)
&lt;class 'int'>
>>> a += 4
>>> a
9   

>>> c = 1.5
>>> c
1.5
>>> type(c+a)
&lt;class 'float'>
>>> 5/2
2.5
>>> 5//2
2
>>> 5**2
25 
  </example>

</slide>
<!--slide title="Cvičení">

  <ol>
    <li>Sečtěte čísla 3, 4 a 5.</li>
    <li>Sečtěte druhé mocniny čísel 3, 4 a 5.</li>
    <li>Ověřte, že pro čísla 3, 4, 5 platí Pythagorova věta, tj. ověřte platnost vztahu <code>3<sup>2</sup>+4<sup>2</sup>=5<sup>2</sup></code>.</li>
    <li>Spočtěte v reálném oboru, kolikrát se vejde číslo 7 do čísla 51.</li>
    <li>Spočtěte v celočíselném oboru, kolikrát se vejde číslo 7 do čísla 51.</li>
    <li>Zjistěte, jaký je zbytek po celočíselném dělení čísla 51 číslem 7.</li>
    <li></li>
  </ol>

</slide-->
<slide title="Příklady – řetězce">

  <example lang="python">
>>> s = "ahoj"
>>> type(s)
&lt;class 'str'>

>>> s + " světe"
'ahoj světe'

>>> len(s)
4

>>> s[0]
'a'
>>> s[-1]
'j' 
  </example>

</slide>
<!--slide title="Cvičení">

  <ol>
    <li>Zjistěte počet znaků ve vašem jméně.</li>
    <li>Vypište první znak vašeho jména.</li>
    <li>Vypište druhý znak vašeho jména.</li>
    <li>Vypište poslední znak vašeho jména.</li>
    <li>Vypište předposlední znak vašeho jména.</li>
    <li></li>
    <li></li>
  </ol>

</slide-->
<slide title="Příklady – přiřazení">

  <p class="enumerate">
    Přiřazování je v Python'u celkem tradiční:
  </p>
  <example lang="python">
>>> a = 'ahoj'
>>> a
'ahoj'
  </example>
  
  <p class="enumerate">
    Lze však provést i vícenásobné přiřazení:
  </p>
  <example lang="python">
>>> a = b = 0
>>> a
0
>>> b
0
  </example>
  
  <p class="enumerate">
    Zdánlivě magicky pak vypadají přiřazování u n-tic, ale na ně se podíváme až v příslušné kapitole.
  </p>

</slide>
<slide title="Příklady – porovnávání">

  <p class="enumerate">
    Porovnávání je v Python'u celkem tradiční:
  </p>
  <example lang="python">
# návratový typ porovnání je Boolean
>>> type(3 == 5)
&lt;class 'bool'>
>>> "bla" == 'bla'
True

# proměnné se porovnávají klasicky
>>> a = b = 0
>>> a == b
True
  </example>
  
  <p class="enumerate">
    Kromě tradičního skládání pravdivostních hodnot..
  </p>
  <example lang="python">
>>> False and False or True
True

>>> not True
False 
  </example>
  <p>
    ..však můžeme v Python'u provést i následující:
  </p>
  <example lang="python">
>>> n = 33

# Složená podmínka:
>>> 1 &lt; n &lt; 100
True

# Její tradiční ekvivalentní (a hůře čitelný) zápis:
>>> (1 &lt; n) and (n &lt; 100)
True

# Zcela v duchu tohoto rozpisu je pak jasný následující výsledek:
>>> 1 &lt; -10 &lt; 100
False
  </example>
  <note>
    Komentářové řádky s <em>#</em> nejsou součástí výpisu konzole.
  </note>

</slide>
<slide title="Příklady – „is“ versus „is not“">

  <example lang="python">
# A) neproměnné typy
>>> a = 1
>>> b = 1
>>> a == b
True
>>> a is b
True

# B) proměnné typy
>>> a = [1]
>>> b = [1]
>>> a == b
True
>>> a is b
False
>>> a is not b
True
  </example>
  <note>
    Komentářové řádky s <em>#</em> nejsou součástí výpisu konzole.
  </note>

</slide>
<slide title="Sekvence">

  <p>
    Sekvence jsou vůbec nejdůležitější pythonovský datový typ. Obecně jsou to konečné uspořádané skupiny prvků indexovaných nezápornými čísly, a ač se od sebe v konkrétních vlastnostech často dosti liší, mnoho vlastností a metod základních mají společných:
  </p>
  <ul>
    <li>
      <example lang="python">len(xs)</example>
      vrací délku příslušné sekvence <code>xs</code>
    </li>
    <li>
      <example lang="python">xs[i]</example>
      vrací prvek sekvence na pozici <code>i</code> (smysl má i výraz typu <code>xs[-2]</code>)
    </li>
    <li>
      <example lang="python">xs[i:j]</example>
      vrací podsekvenci od indexu <code>i</code> po index <code>j-1</code> (smysl mají i výrazy typu <code>xs[:3]</code>, <code>xs[-2:]</code> apod., někde též <code>xs[i:j:k]</code>)
    </li>
    <li>
      <example lang="python">zs = xs + ys</example>
      spojování sekvencí
    </li>
    <li>
      <example lang="python">for x in xs:</example>
      smyčka přes všechny prvky sekvence
    </li>
    <li>
      <example lang="python">x in xs</example>
      zjištění výskytu prvku v sekvenci
    </li>
    <li>
      <example lang="python">xs.index(x[, n])</example>
      zjištění prvního umístění prvku v sekvenci (od pozice <code>n</code>)
    </li>
    <li>
      <example lang="python">xs.count(x)</example>
      počet výskytů prvku <code>x</code> v sekvenci <code>xs</code>
    </li>
  </ul>

</slide>
<slide title="Sekvence – příklady">

  <p>
    Pár příkladů na řetězcích (ale úplně stejně to funguje i pro bajtové řetězce a pole, seznamy a n-tice a velmi podobně i pro množiny a slovníky):
  </p>
  <example lang="python">
>>> s = "Ahoj, světe!"

>>> len(s)
12

>>> s[0]
'A'
>>> s[-2]
'e'
>>> s[2:5]
'oj,'
>>> s[:5]
'Ahoj,'
>>> s[-4:]
'ěte!'
>>> s[2:9:3]
'o ě'

>>> for c in s:
...     print(c, end=' ')
...
A h o j ,   s v ě t e ! >>>

>>> 'A' in s
True
>>> 'a' in s
False
  </example>

  <handout>
    Nejrozsáhlejší datový typ.
    
    http://www.python.org/doc/3.0.1/reference/datamodel.html
    Sequences
      immutable: Strings, Tuples, Bytes
      mutable:   Lists, Byte Arrays
    Set types
      Sets
      Frozen sets
    Mappings
      Dictionaries
  </handout>

</slide>
<slide title="Řetězce">

  <p>
    Řetězce v Python'u 3.X jsou automaticky unicodové =&gt; každý jeden viditelný znak je reprezentován proměnným počtem bajtů.
  </p>
  <note>
    Narozdíl od Python'u 2.x, kde bylo třeba unicodové řetězce specielně označit <code>u''</code>, jinak byly pokládány za sekvence bajtů v nějakém (předem neurčeném) kódování.
  </note>
  <p>
    Řetězce patří mezi sekvence, a to neměnitelné (<i>immutable</i>). Vztahují se na ně proto všechny poznámky o sekvencích.
  </p>
  <p>
    Speciální vlastnosti řetězců:
  </p>
  <ul>
    <li>
        formátování:
        <example lang="python">
            jméno, průměr = 'cosi', 1/3

            f"Prvek {jméno} by měl mít průměr {průměr:.3} cm."
        </example>
        <br/>
        <example lang="python">
            jméno, průměr = 'cosi', 1/3
            
            "Prvek {0} by měl mít průměr {1:.3} cm.".format(jméno, průměr)
            
            "Prvek {jmeno} by měl mít průměr {prumer:.3} cm.".format(
                                                                jmeno='cosi',
                                                                prumer=1/3 ,
                                                              )
        </example>
    </li>
  </ul>
  <note>
    Původní způsob formátování z Python'u 2.x
    <example lang="python">
        '%(lang)s has %(#)03d quote types.' % {
                                                "lang": "Python",
                                                "#": 2,
                                              }
    </example>
    který dává výstup <code>'Python has 002 quote types.'</code>, je v řadě 3.x zatím ještě podporován, i když je označen jako vlastnost/kód určená k budoucímu vyřazení.
  </note>
  <ul>
    <li>
        dotazy na obsah:
        <example lang="python">
            xs.isalpha()
            xs.isdigit()
            xs.isspace()
            xs.islower()
        </example>
        atd.
    </li>
    <li>
        analýza obsahu:
        <example lang="python">
            xs.count("ho")
            xs.endswith("!")
            xs.find("!")
            xs.rfind("!")
        </example>
        atd.
    </li>
    <li>
        velikost písmen:
        <example lang="python">
            xs.swapcase()
            xs.upper()
            xs.title()
        </example>
        atd.
    </li>
    <li>
        „prázdné“ znaky &amp;:
        <example lang="python">
            xs.strip(['ZNAK[Y]'])
            xs.lstrip(['ZNAK[Y]'])
            xs.center(DELKA[,'ZNAK'])
            xs.rjust(DELKA[,'ZNAK'])
        </example>
        atd.
    </li>
    <li>
        záměna:
        <example lang="python">xs.replace('CO', 'ČÍM'[, 'KOLIKRÁT'])</example>
    </li>
    <li>
        rozdělování (vrací seznam podřetězců):
        <example lang="python">
            xlist = xs.split(['ZNAK[Y]'])
            xlist = xs.splitlines()
        </example>
    </li>
    <li>
        spojování (prvků iterovatelného typu):
        <example lang="python">xs = 'SPOJOVACÍ ŘETĚZEC'.join(xlist)</example>
    </li>
  </ul>

</slide>
<slide title="Seznamy">

  <p>
    Seznamy jsou také sekvenční (tedy uspořádaný) typ, ale jsou ale měnitelné (<i>mutable</i>), proto také většina jejich metod „operuje“ přímo na příslušném seznamu a málokdy něco vrací.
  </p>
  <p>
    Prvky seznamu jsou sice typicky jednoho typu, ale to není pravidlo – seznam může obsahovat prakticky cokoliv (samozřejmě i jiné seznamy).
  </p>
  <p>
    Speciální vlastnosti seznamů:
  </p>
  <ul>
    <li>
      přidání prvků do seznamu:
      <example lang="python">
        xs.append(PRVEK)
        xs.insert(POZICE, PRVEK)
        xs.extend(SEZNAM)
      </example>
    </li>
    <li>
      odebrání prvku ze seznamu:
      <example lang="python">
        xs.remove(x)
        del xs[i]         # obecná obdoba předchozího
        x = xs.pop([i])
      </example>
    </li>
    <li>
      operace nad celým seznamem:
      <example lang="python">
        xs.reverse()
        xs.sort()
      </example>
    </li>
  </ul>

</slide>
<slide title="N-tice">

  <p>
    N-tice jsou neměnitelný (<i>immutable</i>) sekvenční typ. Zjednodušeně se o nich dá uvažovat jako o „zmražených“ seznamech (ostatně zkuste si <code>dir(xs)</code> na nějakou ntici :-), i když se toto pojetí míjí s jejich pravděpodobným původním záměrem.
  </p>
  <p>
    Použití nachází často např. jako návratové hodnoty z funkcí, protože díky vlastnosti „zabalování a rozbalování“ n-tice umožňují snadno přenést více hodnot v jednom „balíku“ v <b>zaručeném pořadí</b>:
  </p>
  <example lang="python">
    t = ('ahoj', 234, ['a', 3, 5],)
    a, b, c = t
  </example>
  <notes>
    <note>
      Konstruktorem (neprázdné) n-tice je čárka, závorky je tudíž možné vynechat.
    </note>
    <note>
      Při rozbalování pozor – proměnných na levé straně musí být stejný počet jako prvků n-tice! (Nebo musíte použít např. trik s operátorem <code>*</code>.)
    </note>
  </notes>
  <p>
    Oblíbený pythoní trik pro výměnu obsahu dvou proměnných využívající rozbalování n-tic pak vypadá následovně:
  </p>
  <example lang="python">
    a, b = b, a
  </example>
  <p>
    Dejte si ale pozor na porovnávání – vynechané závorky někdy dokážou n-tice úspěšně „zamaskovat“:
  </p>
  <example lang="python">
>>> (1, 2) == (1, 2)
True
>>> (1, 2) == (1, 2, )
True
>>> 1, 2 == 1, 2
(1, False, 2) 
  </example>

</slide>
<slide title="Přiřazování za pomoci n-tic">
  
  <p>
    Díky existenci datové typu <strong>n-tice</strong> se můžeme v Python'u pěkně „vyřádit“ při přiřazování (a to mnohem více než u již ukázaného triku <code>a, b = b, a</code>):
  </p>
  
  <p class="enumerate">
    Přiřazení více hodnot více proměnným najednou:
  </p>
  <example lang="python">
>>> v1, v2 = 1.3, "ahoj"
>>> v1
1.3
>>> v2
'ahoj'

>>> del v1
>>> v1
Traceback (most recent call last):
  File "&lt;stdin>", line 1, in &lt;module>
NameError: name 'v1' is not defined

>>> v2
'ahoj'
  </example>
  <note>
    Uvedený zápis „funguje“ proto, že na obou stranách operátoru přiřazení <code>=</code> se nachází n-tice o dvou členech.
  </note>
  <handout>
 1   a = 1
 2   print a
 3   del a     # we remove the variable a
 4   print a   # this will cause an error because a is not defined
  </handout>
  
  <p class="enumerate">
    Přiřazení blíže neurčeného počtu dat do menšího počtu proměnných za pomoci operátoru <code>*</code>:
  </p>
  <example lang="python">
>>> a, *b, c = 'první', 1, 2, 'ahoj', 'poslední'
>>> a
'první'
>>> b
[1, 2, 'ahoj']
>>> c
'poslední'
  </example>
  <note>
    „Ohvězdičkovaná“ proměnná pod sebe „schramstne“ všechny přebytečné hodnoty (a ve většině případů se tak stane n-ticí).
  </note>

</slide>
<slide title="Slovníky">

  <p>
    Slovník v Python'u je asi nejpodobnější heš-tabulkám z jiných jazyků. Jeho struktura je následující:
  </p>
  <example lang="python">
    slovnik = {
      KLÍČ1: HODNOTA1,
      KLÍČ2: HODNOTA2,
      ...
    }
  </example>
  <p>
    Zatímco <i>hodnotou</i> může být cokoliv, <i>klíč</i> musí být hešovatelný datový typ (tj. neměnný, <i>immutable</i>)! Typicky se indexuje řetězcem nebo číslem, ale stejně tak dobře můžete použít například n-tici, <b>pokud</b> se sama skládá z neměnných typů.
  </p>
  
  <p>Vlastnosti slovníků:</p>
  <ul>
    <li>
      pořadí párů <i>klíč–hodnota</i> je neurčené<sup>*</sup>, k prvkům slovníku se tak nedá přistupovat podle indexu, zato jsou ale optimalizovány na přístup podle klíče:
      <example lang="python">
        >>> d = { 'a': 1, 'b': [1,2,3], 'c': "ahoj", }
        >>> d['b']
        [1, 2, 3]
      </example>
      <note>
        <sup>*</sup> Od Python'u 3.6 si drží pořadí podle zavedení.
      </note>
    </li>
    <li>
      přiřazení hodnoty do již existujícího klíče starou hodnotu nahradí novou:
      <example lang="python">
        >>> d['a'] = "svet"
        >>> d
        {'a': 'svet', 'c': 'ahoj', 'b': [1, 2, 3]}
      </example>
    </li>
    <li>
      úplně stejným způsobem přidáte do slovníku nový pár <i>klíč–hodnota</i>:
      <example lang="python">
        >>> d[123] = (1, 'tuple')
        >>> d
        {'a': 'svet', 123: (1, 'tuple'), 'c': 'ahoj', 'b': [1, 2, 3]}
      </example>
    </li>
    <li>
      a nepotřebného páru se zbavíte pomocí univerzálního <code>del</code>:
      <example lang="python">
        >>> del d['b']
        >>> d
        {'a': 'svet', 123: (1, 'tuple'), 'c': 'ahoj'}
      </example>
    </li>
    <li>
      počet párů <i>klíč–hodnota</i> ve slovníku:
      <example lang="python">len(d)</example>
    </li>
    <li>
      dotaz na výskyt klíče <code>key</code> ve slovníku <code>d</code>:
      <example lang="python">key in d</example>
    </li>
    <li>
      pohled/iterátor přes klíče, resp. hodnoty>
      <example lang="python">
        d.keys()
        d.values()
      </example>
    </li>
    <li>
      pohled/iterátor přes páry (vrací postupně n-tice tvaru <code>(KLÍČ, HODNOTA)</code>):
      <example lang="python">d.items()</example>
    </li>
    <li>
      některé další metody slovníků:
      <example lang="python">
          d1.update(d2)
          d.clear()
          d.popitem()
          d.pop(KEY)
          d.copy()
      </example>
    </li>
    <li>
      cyklus <i>for</i> přes slovník v nejpřirozenějším zápise iteruje přes klíče:
      <example lang="python">
        for i in d:
            print(i)
      </example>
    </li>
    <li>
      následující cyklus „rozbalí“ z n-tice zároveň klíč i hodnotu:
      <example lang="python">
        for (key, val) in d.items():
            print( key, val, sep=': ' )
      </example>
    </li>
    <li>
      <b>pokud</b> jsou klíče navzájem porovnatelné, můžeme podle nich páry ve slovníku setřídit:
      <example lang="python">
        for key in sorted(d):
            print( key, d[key], sep=': ' )
      </example>
      <note>
        Pozor: Toto setřídění se týká pouze aktuálně prováděného průchodu přes prvky slovníku! Následující průchod slovníkem bez třídění opět vypíše záznamy v (pseudo)náhodném pořadí, resp. v pořadí zadání (od verze 3.6).
      </note>
    </li>
  </ul>

</slide>
<slide title="Množiny">

  <p>
    Množina je <i>neuspořádaná</i> kolekce <b>jedinečných</b> <i>hodnot</i> (a to neměnných, <i>immutable</i>):
  </p>
  <example lang="python">
>>> xs = { 1, 2, 'ahoj', 3, 'b', }
>>> xs
{3, 1, 2, 'b', 'ahoj'}
  </example>
  <p>
    Kromě standardních operací <code>len(xs)</code> a <code>x in xs</code> a operací na prvcích..
  </p>
  <ul>
    <li>
      přidání hodnot(y):
      <example lang="python">
        xs.add(VALUE)
        xs.update([SET|LIST]+)
      </example>
    </li>
    <li>
      odebrání hodnoty:
      <example lang="python">
          xs.discard(VALUE)
          xs.remove(VALUE)   # „KeyError“ pro neexistující hodnotu
          x = xs.pop()       # „KeyError“ pro prázdnou množinu
      </example>
    </li>
    <li>
      smazání množiny:
      <example lang="python">xs.clear()</example>
    </li>
    <li>
      (mělká) kopie množiny:
      <example lang="python">ys = xs.copy()</example>
    </li>
  </ul>
  <p>
     ..máme pro množiny k dispozici i skutečně množinové operace typu <i>sjednocení</i>, <i>průnik</i>, <i>je podmnožinou?</i> a podobně:
  </p>
  <ul>
    <li>
      vracející novou množinu:
      <example lang="python">
          xs.difference(ys)             # též xs-ys
          xs.symmetric_difference(ys)   # též xs^ys
          xs.intersection(ys)           # též xs&amp;ys
          xs.union(ys)                  # též xs|ys
      </example>
    </li>
    <li>
      vracející <i>Boolean</i>:
      <example lang="python">
          xs.isdisjoint(ys)
          xs.issubset(ys)     # též xs&lt;[=]ys
          xs.issuperset(ys)   # též xs&gt;[=]ys
      </example>
    </li>
  </ul>

</slide>
<slide title="Přiřazení – proměnné a neproměnné typy">
  
  <handout>Přiřazení (či spíše „pojmenovávání“)</handout>
  
  <p>
    Proměnné (<i>mutable</i>) typy jsou v Python'u předávány odkazem, neproměnné (<i>immutable</i>) prozměnu zase hodnotou:
  </p>
  <example lang="python">
>>> xs = ['a', 'h', 'o', 'j']
>>> ys = xs
>>> ys
['a', 'h', 'o', 'j']

>>> xs.remove('o')
>>> xs
['a', 'h', 'j']
>>> ys
['a', 'h', 'j']
  </example>
  <note>
    Na začátku si na tom asi párkrát nabijete nos, ale časem na tuhle nakonec celkem logickou podivnost (zvanou, pokud vůbec nějak, <em>předávání objektem</em>) zvyknete.
  </note>

</slide>
<slide title="Třídění">

  <p class="enumerate">
    Základní třídění (řazení) v Python'u je lexikografické, po složkách a stabilní:
  </p>
  <example lang="python">
>>> xs = [ ('Láďa', 2), ('Jana', 2), ('Jana', 1), ('Karel', 3) ]

>>> sorted(xs)
[('Jana', 1), ('Jana', 2), ('Karel', 3), ('Láďa', 2)]
  </example>
  <p>
    Python obecně bude třídit všechny objekty, které interně implementují „magickou“ metodu <code>__lt__()</code>, tedy <em>menší než</em>, pro porovnání svých prvků. Ve výchozím stavu to znamená všechny předdefinované typy.
  </p>
  
  <p class="enumerate">
    Pomocí parametru <em>key</em> se toto chování dá změnit:
  </p>
  <example lang="python">
>>> xs = [ ('Láďa', 2), ('Jana', 1), ('Karel', 3) ]

>>> sorted( xs, key = lambda c: c[0] )
[('Jana', 1), ('Karel', 3), ('Láďa', 2)]

>>> sorted( xs, key = lambda c: c[1] )
[('Jana', 1), ('Láďa', 2), ('Karel', 3)]
  </example>
  <p>
    PS: <code>xs.sort([key=])</code> by změnilo přímo seznam <code>xs</code>.
  </p>

</slide>
<slide title="Generátorová notace">
  
  <p>
    <strong>Generátorová notace</strong> (<i>comprehensions</i>) je způsob, jak průchodem po iterovatelném typu snadno a elegantně (typicky v jedné řádce) vyrobit seznam / slovník / množinu. V případě seznamu (notace pro množiny a slovníky je velmi podobná) je obecný zápis:
  </p>
  <blockquote>
    „[“ Funkce(I) for I in SEKVENCE [if PODMÍNKA] „]“
  </blockquote>
  
  <p>
    Pár příkladů pro seznam:
  </p>
  <example lang="python">
>>> xs = range(1, 9)
>>> xs
range(1, 9)
>>> list(xs)
[1, 2, 3, 4, 5, 6, 7, 8]

>>> [2**n for n in xs]
[2, 4, 8, 16, 32, 64, 128, 256]

>>> [n for n in xs if n % 2 == 0]
[2, 4, 6, 8]
  </example>

</slide>
<!--slide title="Základní řídící konstrukce">

  <p>
    Vynucený blokový zápis prakticky všech příkazů je jedním z klasických „rozpoznávacích znaků“ Python'u. Avšak jelikož <em>prázdné</em> a <em>komentářové</em> řádky se do bloku nezpočítávají, je u delších bloků i tak relativně jednoduché jinak většinou krásně přehledný pythoní kód pěkně znečitelnit.
  </p>
  <p>
    V následujícím přehledu základních řídících konstrukcí Python'u si prosím všimněte zvláště použití odsazování jako oddělovače bloků!
  </p>

</slide-->
<slide title="Větvení „if“">

  <p>
    Podmíněný příkaz <em>větvení</em> je v Python'u celkem standardní:
  </p>
  <example lang="python">
 if PODMÍNKA1:
    BLOK
 elif PODMÍNKA2:
    BLOK
 else:
    BLOK
  </example>
  <p>
    Přitom:
  </p>
  <ul>
    <li>
        větve <code>elif</code> a <code>else</code> nejsou povinné
    </li>
    <li>
        <em>elifů</em> může být libovolně mnoho
    </li>
  </ul>
  <p>
    Poznámka: V Python'u nejsou konstrukce typu <em>switch / case</em>. Ve většině případů se nahrazují právě <em>elify</em>, v odůvodněných případech přímým voláním na základě slovníkových klíčů.
  </p>

</slide>
<slide title="Příklady – „if“">

  <example lang="python">
>>> if 4 == 5:
...     print('foo')
... else:
...     print('bar')
... 
bar 
  </example>
  <br/>
  <example lang="python">
>>> a = "foo"
>>> if a in ['červená', 'zelená', 'modrá']:
...     print( a + " je barva." )
... elif a in ['jedna', 'dvě', 'tři']:
...     print( a + " je číslo." )
... else:
...     print( "Nevím, co je " + a + "." )
... 
Nevím, co je foo. 
  </example>

</slide>
<slide title="Podmíněný výraz („ternární operátor“)">

  <p>
    Narozdíl od mnoha jiných věcí bylo volání po <strong>podmíněném výrazu</strong> vyslyšeno a od Python'u 2.5 je k dispozici v následující pododě:
  </p>
  <example lang="python">
    výstup = VÝRAZ1 if PODMÍNKA else VÝRAZ2
  </example>
  <p>
    Pořadí zápisu je tedy mezi programovacími jazyky velmi nezvyklé (typicky bývá pomínka první, viz např. <code>PODMÍNKA ? VÝRAZ1 : VÝRAZ2</code>), ale z hlediska Python'u nakonec zcela přirozené.
  </p>

</slide>
<!--slide title="Cvičení">

  <ol>
    <li>Vypište větší ze dvou zadaných čísel.</li>
    <li>Upravte předchozí program – vypište obě zadaná čísla se slovním komentářem, které z nich je větší.</li>
    <li>Zopakujte si předchozí příklad, ale zajímejte se o menší číslo.</li>
    <li>Ukažte výsledek porovnání délek (počtu písmen) obou částí vašeho jména.</li>
    <li></li>
    <li>Vyzkoušením obou možností uzávorkování zjistěte na výrazu <code>False and False or True</code>, který z logických operátorů <em>and</em> a <em>or</em> má vyšší prioritu.</li>
    <li>Zopakujte si předchozí příklad pro zadání <code>0 and '' or "Ahoj!"</code>. Co zjistíte?</li>
  </ol>

</slide-->
<slide title="Předčasné ukončení smyčky">

  <p>
    Python umožňuje smyčku, resp. celý cyklus, předčasně ukončit. Slouží k tomu dva klasické příkazy:
  </p>
  <ul>
    <li>
        <example lang="python">continue</example>
        ukončí aktuální smyčku a pokračuje následující
    </li>
    <li>
        <example lang="python">break</example>
        ukončí celý aktuální cyklus a přejde na kód následující po něm
    </li>
  </ul>

</slide>
<slide title="Cyklus „for“">

  <p class="enumerate">
    Narozdíl od snad naprosté většiny programovacích jazyků se v Python'u cyklí průchodem po prvcích nějakého objektu, ve většině případů sekvence:
  </p>
  <example lang="python">
 for i in SEKVENCE:
    BLOK
  </example>
  <note>
    Navíc narozdíl od většiny ostatních jazyků je proměnná cyklu (zde <code>i</code>) definována na stejné úrovni kódu jako sama smyčka, takže po skončení cyklu bude stále existovat a mít právě tu hodnotu, jíž během provádění cyklu dosáhla (zde poslední prvek procházené sekvence).
  </note>
  
  <p class="enumerate">
    Přímou obdobou klasického <em>for</em>-cyklu je pak průchod po prvcích odpovídajícího rozsahu:
  </p>
  <example lang="python">
 for i in range(INTERVAL):
    BLOK
  </example>
  
  <p class="enumerate">
    Naopak zcela neklasickou je varianta s větví <em>else</em>:
  </p>
  <example lang="python">
for i in SEKVENCE:
   BLOK 1
else:
   BLOK 2
  </example>
  <p>
    Větev s <code>else</code> se provede pouze tehdy, je-li cyklus ukončen normálně, tedy dojde-li k proiterování všech prvků vstupní sekvence. Naopak je-li cyklus v <em>BLOKu 1</em> ukončen násilně pomocí <code>break</code>, kód v <em>BLOKu 2</em> nebude vůbec vykonán. 
  </p>

</slide>
<slide title="Příklady – „for“">

  <p class="enumerate">
    Zde je vstupním objektem, po jehož prvcích se iteruje, seznam tří řetězců:
  </p>
  <example lang="python">
>>> for word in ["welcome", "to", "python"]:
...     print(word)
...
welcome
to
python
  </example>
  
  <p class="enumerate">
    Po tomtéž seznamu zde iterujeme za dodatečné pomoci funkce <code>enumerate()</code>, která navíc vrací pořadí prvků v objektu:
  </p>
  <example lang="python">
>>> for i, word in enumerate(["welcome", "to", "python"]):
...     print(i, word)
...
0 welcome
1 to
2 python
  </example>
  <note>
    Všimněte si použití n-tice na místě řídících proměnných cyklu.
  </note>

</slide>
<!--slide title="Cvičení">

  <ol>
    <li>Vypište si postupně všechna písmena ve vašem jméně.</li>
    <li>Vypište všechna čísla od 0 do 10.</li>
    <li>Vypište 11x pozdrav <em>Ahoj!</em></li>
    <li>Sečtěte čísla mezi 0 a 10.</li>
    <li>Rozšiřte předchozí příklad – spočítejte průměrnou hodnotu z daných čísel. (Použijte funkci <em>len()</em> na příslušný rozsah.)</li>
    <li>Vypište z vašeho jména každý druhý znak.</li>
    <li>Vypište z vašeho jména každý třetí znak.</li>
  </ol>

</slide-->
<slide title="Příklady – „range“">

  <p>
    Rozsahy <code>range()</code>:
  </p>
  <example lang="python">
>>> range(5)
range(0, 5)
>>> type( range(5) )
&lt;class 'range'>
>>> list( range(5) )
[0, 1, 2, 3, 4] 

>>> range(4,6)
range(4, 6)
>>> list( range(4,6) )
[4, 5] 

>>> range(1,7,2)
range(1, 7, 2)
>>> list( range(1,7,2) )
[1, 3, 5] 
  </example>
  <p>
    Jejich použití ve smyčce:
  </p>
  <example lang="python">
>>> sum = 0
>>> for i in range(10):
...     sum += i
... 
>>> sum
45 
  </example>

</slide>
<slide title="Ukázka – prvočísla">
  
  <p>
    Hodně neklasicky, ale neoptimalizovaně:
  </p>
  <example lang="python">
>>> for n in range(100):
...     for x in range(2,n):
...         if n % x == 0:
...             break
...     else:
...         print( n, end=' ')
... 
0 1 2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97 >>>  
  </example>
  
  <p>
    Poznámka: Větev s <strong>else</strong> u cyklu <em>for</em> se provede pouze tehdy, je-li for-cyklus ukončen normálně, tedy nikoli právě na <em>break</em>.
  </p>

</slide>
<!--slide title="Cvičení">

  <p>
    Vytvořte následující rozsahy:
  </p>
  <ol>
    <li>čísla od 0 do 7</li>
    <li>čísla od 3 do 9</li>
    <li>čísla od 0 do 11 s krokem 2</li>
    <li>čísla od 3 do 13 s krokem 3</li>
    <li>lichá čísla od 10 do 20</li>
  </ol>
  <p>
    V následujících příkladech použijte záporný krok:
  </p>
  <ol>
    <li>čísla od 11 do 7</li>
    <li>čísla od 11 do 4 s krokem 2</li>
    <li>lichá čísla od 20 do 10</li>
  </ol>

</slide-->
<slide title="Cyklus „while“">

  <p class="enumerate">
    Cyklus <em>while</em> je na první pohled obdobný jako všude jinde:
  </p>
  <example lang="python">
     while PODMÍNKA:
         BLOK
  </example>
  <p>
    Až do Python'u 3.8 platilo, že v rámci podmínky není možné provést přiřazení do proměnné, ale se zavedením nového speciálního výrazu <code>:=</code> už to dnes jde, takže můžete psát:
  </p>
  <example lang="python">
      while (block := f.read(256)) != '':
          process(block)
  </example>
  <note>
    Python byl totiž původně navržen jako jazyk se striktním rozdělením konstrukcí na příkazy a výrazy. A i když to dnes již není na mnoha místech pravda, přiřazení <code>=</code> výrazem není, takže ho nebylo možné použít místo podmínky. Navíc zrovna v tomto místě to bylo zdůvodňováno jen a pouze snadnou záměnou <code>==</code> za <code>=</code>, což nakonec opravdu spravilo právě zavedení jiného způsobu přiřazování (<code>:=</code>). Jinak holt za jazykem nerozlišujícím mezi výrazy a příkazy je se třeba podívat jinam.
  </note>

  <p class="enumerate">
    Podobně jako u příkazu <em>for-in</em> i pro <em>while</em> existuje velmi neklasická varianta s větví <em>else</em>:
  </p>
  <example lang="python">
    while PODMÍNKA:
       BLOK 1
    else:
       BLOK 2
  </example>
  <p>
    Větev s <code>else</code> se provede pouze tehdy, je-li smyčka <em>BLOKu 1</em> ukončena normálně na <em>PODMÍNKu</em>, a je vynechána při jejím násilném ukončení (příkazem <code>break</code>).
  </p>

</slide>
<slide title="A co „repeat“?">
  
  <p>
    V Python'u není cyklus <em>repeat</em>. Nahrazuje se použitím následující konstrukce:
  </p>
  <example lang="python">
     while True:
         BLOK
         if PODMÍNKA: break
  </example>
  
</slide>
<slide title="Příklady – „while“">

  <p class="enumerate">
    Klasické použití:
  </p>
  <example lang="python">
>>> i = 0
>>> while i &lt; 5:
...     print(i)
...     i += 1
... 
0
1
2
3
4 
  </example>
  
  <p class="enumerate">
    Náhrada <em>repeat-until</em>:
  </p>
  <example lang="python">
>>> while True:
...     print( "ahoj" )
...     break
... 
ahoj 
  </example>
  <note>
    Aneb velmi složitý způsob, jak jednou vypsat řetězec <em>ahoj</em> ^_^
  </note>

</slide>
<!--slide title="Cvičení">

  <ol>
    <li>Vypište 11x pozdrav <em>Ahoj!</em></li>
    <li>Vypište postupně čísla 0 až 9, tj. takto vzestupně.</li>
    <li>Vypište postupně čísla 9 až 0, tj. takto sestupně.</li>
    <li></li>
    <li>Vypište postupně všechna písmenka ve vašem jméně. (Procházejte řetězec s vaším jménem po indexech a zaražte se na správné délce. Tj. použijte notaci <em>[]</em> a funkci <em>len()</em>.)</li>
    <li>Vypište z vašeho jména každý druhý znak.</li>
    <li></li>
  </ol>

</slide-->
<slide title="Operátor „:=“ (aka „walrus“)">

    <p>
        Od Python'u 3.8 je možno použít nový přiřazovací operátor <code>:=</code> (zvaný z pochopitelných důvodů <em>walrus</em> :-), <strong>který je</strong> dohromady s okolostojící proměnnou a výrazem také <strong>výrazem</strong> (a ne příkazem, jako běžný operátor přiřazení <code>=</code>).
    </p>
    <p>
        Ač nejznámější použití je pravděpodobně v <a href="?slajd=43">podmínce cyklu <em>while</em></a>, v Python'u dává smysl i na mnoha dalších místech, například:
    </p>
    <example lang="python">
# netřeba volat "len()" dvakrát na to samé
if (n := len(a)) > 10:
    print(f"List is too long ({n} elements, expected &lt;= 10)")

# netřeba provádět stejný regexp-match dvakrát
discount = 0.0
if (mo := re.search(r'(\d+)% discount', advertisement)):
    discount = float(mo.group(1)) / 100.0

# použití získané hodnoty v podmínce filtru a zároveň i v těle generátorové notace
[clean_name.title() for name in names
 if (clean_name := normalize('NFC', name)) in allowed_names]

# použití získané hodnoty v podmínce cyklu a zároveň i v jeho těle
while (block := f.read(256)) != '':
    process(block)
    </example>
    <note>
        Bez invence přímo opsáno <a href="https://docs.python.org/3.8/whatsnew/3.8.html#assignment-expressions" class="external">z dokumentace</a>.
    </note>

</slide>
<slide title="Výjimky – „try-except“">

  <p class="enumerate">
    Pro odchycení a zpracování „havarijních“ situací za běhu programu máme k dispozici výjimky:
  </p>
  <example lang="python">
    try:
      BLOK-1
    except VÝJIMKA-1:
      BLOK-2
    except VÝJIMKA-2:
      BLOK-3
  </example>
  <note>
    Kde <em>VÝJIMKA</em> je některá z hromady předdefinovaných nebo naše vyrobená např. jako potomek třídy <em>Exception</em>:
    <example lang="python">
        class MyError(Exception):
            pass
    </example>
  </note>
  
  <p class="enumerate">
    K bloku <em>try</em> existuje několik dalších užitečných variant:
  </p>
  <ul>
    <li>
      odchycení výjimky jako pojmenovaného objektu
      <example lang="python">
        try:
          BLOK-1
        except VÝJIMKA as ex:
          BLOK-2   # zde je možné použít objekt odchycené výjimky pod jménem 'ex'
      </example>
    </li>
    <li>
      odchycení více výjimek v jedné větvi
      <example lang="python">
        try:
          BLOK-1
        except (VÝJIMKA-1, VÝJIMKA-2, ...):
          BLOK-2
      </example>
    </li>
  </ul>
  
  <p class="enumerate">
    Kdybyste potřebovali výjimkou přeposlat dál, slouží k tomu příkaz <code>raise</code>. Kromě toho můžete minimálně pro lepší čitelnost (v neoptimalizovaném) kódu použít příkaz <code>assert</code>.
  </p>

</slide>
<slide title="Výjimky – „try-except-else-finally“">

  <p>
    Kromě výše uvedených nabízí výjimky ještě dvě další možnosti:
  </p>
  
  <p class="enumerate">
    Větev <em>else</em>:
  </p>
  <example lang="python">
    try:
      BLOK-1
    except:
      BLOK-2
    else:
      BLOK-3
  </example>
  <p>
    <em>BLOK-3</em> bude proveden pouze tehdy, nevyvolal-li kód v <em>BLOKu-1</em> výjimku (jinak tedy že byl přeskočen <em>BLOK-2</em>).
  </p>
  
  <p class="enumerate">
    Větev <em>finally</em>:
  </p>
  <example lang="python">
    try:
      BLOK-1
    except:
      BLOK-2
    finally:
      BLOK-3
  </example>
  <p>
    Kód v <em>BLOKu-3</em> bude proveden <strong>vždy</strong>, naprosto nezávisle na nastalých výjimkách a jejich odchycení.
  </p>
  <note>
    Nepřekvapivě se tento způsob zápisu používá nejen pro „skutečné“ výjimky, ale také pro části programu, po nichž je třeba zajistit „vyčišťovací“ operace (uzavírání souborů apod.).
  </note>

</slide>
<slide title="Příklady – výjimky">

  <p>
    Souhrnně je výjimka poměrně složitá – ale také mocná – konstrukce:
  </p>
  <example lang="python" src="exceptions/_files/try_except.py" />
  <note>
    Upraveno podle <a href="http://www.swaroopch.com/notes/Python_en:Exceptions">http://www.swaroopch.com/notes/Python_en:Exceptions</a>
  </note>

</slide>
<slide title="Blok „with“">

  <p>
    Filozofii za blokem <em>try-finally</em> dovádí k dokonalosti blok <em>with</em>:
  </p>
  <example lang="python">
    with OBJEKT as JMÉNO:
        BLOK
  </example>
  <p>
    Pro objekty, které podporují kontextové zpracování (což jsou z těch důležitějších například soubory), blok <em>with</em> přehlednějším způsobem nahrazuje konstrukci <em>try-except-finally</em>:
  </p>
  <blockquote>
    Při vstupu do <em>kontextu</em> objektu je zavolána jeho „magická“ metody <code>__enter__()</code> a při jeho opuštění – nezávisle na případných vyvolaných výjimkách – metoda <code>__exit__()</code>.
  </blockquote>
  <note>
    V případě souborů to tak třeba znamená, že se nemusíme starat o jejich uzavření – ať už jejich zpracování proběhne v pořádku nebo během něj dojde k libovolné výjimce, soubor bude korektně uzavřen.
  </note>

</slide>
<slide title="Příklady – „with“">

  <p>
    V trojkovém Python'u se kontext <em>with</em> používá nejviditelněji pro práci se soubory:
  </p>
  <example lang="python">
    with open('soubor.txt', mode='r', encoding='utf-8') as soubor:
        for i, řádka in enumerate(soubor):
            print(i, řádka)
  </example>
  <p>
    Jinými slovy se tedy při použití <code>with</code> nemusíte „babrat“ se zavíráním souboru (natožpak kdyby během práce s ním došlo k nějaké výjimce).
  </p>

</slide>
<slide title="Funkce „def“">

  <p class="enumerate">
    Python poskytuje velkou podporu pro definici a používání funkcí.
  </p>
  <note>
    Aby ne, když jsou v něm <em>first class object</em>. (A kromě toho máme také k dispozici hodně ořezané, ale přeci <em>lambda-funkce</em>.)
  </note>
  <p>
    Novou funkci (v nejjednodušším možném tvaru) zavedeme pomocí klíčového slova <code>def</code> takto:
  </p>
  <example lang="python">
    def jméno_nové_funkce():
        BLOK
  </example>
  <note>
    Odsazení <em>BLOKu</em> jako těla funkce už snad netřeba zdůrazňovat.
  </note>
  
  <p class="enumerate">
    Funkce (samozřejmě) mohou mít vstupní parametry a vracet nějaké objekty, jak ukazuje třebas následující příklad:
  </p>
  <example layout="horizontal">
    <program src="_files/funkce4.py" lang="python"/>
    <out src="_files/funkce4.out" lang="text"/>
  </example>
  <p>
    Přitom:
  </p>
  <ul>
    <li>
        Vstupních parametrů může být dokonce proměnný počet.
        <note>Klasickým příkladem je vestavěná funkce <em>print()</em>.</note>
    </li>
    <li>
        Část (nebo i všechny) parametry mohou mít jméno a výchozí hodnotu.
        <note>Pozor pak na předávání proměnných datových typů...</note>
    </li>
    <li>
        Díky datovému typu <em>n-tice</em> může funkce (zdánlivě) vracet více než jednu hodnotu či objekt.
        <note>Což obzvláště v kombinaci s operátory <code>*</code> a <code>**</code> působí občas jako magie.</note>
    </li>
    <li>
        U parametrů můžete vynutit, že některé se musí zadávat se jménem (pomocí <code>*</code>) a některé zase pouze pořadím (pomocí <code>/</code>; od verze 3.8). V následujícím kódu parametry <em>a</em> a <em>b</em> můžete zadat pouze pozičně, parametry <em>e</em> a <em>f</em> pouze jménem a u parametrů <em>c</em> a <em>d</em> si můžete vybrat:
        <example lang="python">
          def f(a, b, /, c, d, *, e, f):
              print(a, b, c, d, e, f)
        </example>
    </li>
  </ul>

</slide>
<slide title="„print()“">
  
  <p>
    Pravděpodobně nejpoužívanější funkce Python'u má syntaxi:
  </p>
  <example lang="python">
print( [object, ...]
       [, sep=' '][, end='\n'][, file=sys.stdout][, flush=False] )
  </example>
  <p>
    Příklad:
  </p>
  <example lang="python">
>>> s1, s2, s3 = 'ahoj', 'světe', 'jak se máš'
>>> print(s1, s2, s3, sep=' | ', end='\n')
ahoj | světe | jak se máš
  </example>

</slide>
<slide title="„input()“">

  <p>
    Spousta běžných skriptů si přebírá parametry pro svůj běh z příkazové řádky. Ale pro jednodušší případy máme k dispozici jakousi protiváhu funkci <em>print</em> – vestavěnou funkci <code>input()</code>. Ta dokáže přebírat vstup (z klávesnice) do běžícího programu.
  </p>

  <p class="enumerate">
    Základní použití spočívá v pouhém zavolání funkce <code>input()</code>:
  </p>
  <example lang="python">
>>> answer = input()
Ahoj, světe!   # tuhle část musíte napsat (a ukončit ↵) sami
>>> answer
'Ahoj, světe!'
  </example>
  <p>
    Uvedený kód čeká na zadání vstupního <strong>řetězce</strong> ukončeného klávesou <code>↵</code>. Zadaný <em>řetězec</em> (bez odřádkování, to jen potvrdilo vstup) je předán jako návratová hodnota funkce (v našem případě tedy do proměnné <em>answer</em>).
  </p>
  <note>
    V Python'u 2.x se tímto způsobem chovala globální funkce <code>raw_input()</code>.
  </note>

  <p class="enumerate">
    Metoda <code>input([PROMPT])</code> má jeden velmi užitečný nepovinný řetězcový parametr, tzv. <em>výzvu</em> (<em>prompt</em>):
  </p>
  <example lang="python">
>>> answer = input('Zadej text: ')
Zadej text: Ahoj, světe!
>>> answer
'Ahoj, světe!'
  </example>
  <note>
    PS: Všimněte si, že kurzor pro vstup je umístěn <em>hned za konec</em> řetězce výzvy. Většinou proto asi nebudete chtít zapomenout na ukončovací mezeru.
  </note>
  <p>
    PS: Chcete-li chování této uživatelské výzvy vylepšit, můžete před jejím použitím naimportovat modul <code>readline</code> (dostupný pouze na platformě Unix!). Vstupní řádka pak „získá“ mimo jiné historii a větší možnosti editace (některé klávesové zkratky apod.).
  </p>

</slide>
<!--slide title="Cvičení">

  <ol>
    <! - -li>Přepište volání funkce <em>faktoriál()</em> z předchozího slajdu tak, aby vstupní číslo mohl zadat uživatel při každém spuštění programu. (Tj. použijte <em>input()</em>.)</li - ->
    <li>Napište funkci, která bude počítat třetí mocninu zadaného čísla.</li>
    <li>Upravte volání předchozí funkce stejně jako u faktoriálu – nechť může vstupní hodnotu zadat uživatel při každém spuštění programu.</li>
    <li>Napište funkci, která bude jako parametr brát jméno a na výstupu vracet pozdrav daného člověka (ignorujte problém pátého pádu v češtině). Jméno zadejte do programu „natvrdo“ v podobě řetězce. (Tj. jde o výpis dvou řetězců.)</li>
    <li>Přepište předchozí funkci stejně jako faktoriál – nechť může jméno zadat uživatel při každém spuštění programu.</li>
    <li></li>
    <li>Napište funkci, která vrátí strukturovaný aktuální čas. (Použijte modul <em>time</em> a jeho metodu <em>time.localtime()</em>.)</li>
  </ol>

</slide-->
<slide title="Funkce a moduly a třídy">

  <p>
    Již jsme viděli, že Python obsahuje spoustu předdefinovaných funkcí již přímo na globální úrovni (v <em>nulovém jmenném prostoru</em>).
  </p>
  <note>
    Nejen podle mého by jich tam mělo být daleko méně. Škoda, že to do trojkové verze neořezali pořádně, když už vyráběli zpětnou nekompatibilitu.
  </note>
  <p>
    Mnohem více funkcí se však schovává na dvou dalších místech:
  </p>
  
  <p class="enumerate">
    Známé jsou <em>funkce jako metody konkrétních objektů</em>:
  </p>
  <example lang="python">
    >>> xs = 'ahoj'
    >>> xs.upper()
    'AHOJ'
  </example>
  
  <p class="enumerate">
    Ne už tak známé jsou <em>funkce ve jmenných prostorech konkrétních modulů</em>. V Python'u totiž každý zdrojový soubor může sloužit jako tzv. <strong>modul</strong>, který je možno pod jeho jménem načíst, naimportovat (za pomoci příkazu <code>import</code> a dalších), čímž se jeho objekty – a to znamená tedy i funkce – stanou přístupnými přes klasickou tečkovou notaci.
  </p>
  <note>
    Pro příklad se podívejte třeba na modul <em>re</em> v distribuci Python'u.
  </note>

</slide>
<slide title="„pprint()“">
  
  <example lang="python">
&gt;&gt;&gt; tup = ('spam', ('eggs', ('lumberjack', 
           ('knights', ))))
&gt;&gt;&gt; stuff = ['a' * 10, tup, ['a' * 10, 'b' * 10], 
             ['c' * 8, 'd' * 8]]

&gt;&gt;&gt; import pprint
&gt;&gt;&gt; pprint.pprint( stuff, width=40 )
['aaaaaaaaaa',
 ('spam',
  ('eggs',
   ('lumberjack', ('knights',)))),
 ['aaaaaaaaaa', 'bbbbbbbbbb'],
 ['cccccccc', 'dddddddd']]
  </example>
  <note>
    Mírně zjednodušený příklad přímo z dokumentace k Python'u.
  </note>

</slide>
<slide title="Ukázka – faktoriál">

  <p class="enumerate">
    Klasicky pomocí rekurzivní funkce:
  </p>
  <example lang="python">
def faktorial(n):
    if n == 0:
        return 1
    else:
        return n * faktorial(n-1)

print( faktorial(9) )
  </example>

  <p class="enumerate">
    Méně přehledně, ale také podstatně méně náročně pomocí obyčejného cyklu:
  </p>
  <example lang="python">
n = 9
out = 1

while n:
    out *= n
    n -= 1

print( out )
  </example>
  <note>
    Podmínka <code>n</code> je sice správná, ale lepší je ji vypsat explicitně jako <code>n >= 0</code>.
  </note>

  <p class="enumerate">
    Líně pomocí knihovní metody modulu <em>math</em>:
  </p>
  <example lang="python">
import math

# Return x factorial. Raises ValueError if x is not integral or is negative.
print( math.factorial(9) )
  </example>

</slide>
<slide title="Třídy „class“">

  <p>
    S třídami v Python'u už jsme se několikrát setkali i v tomto úvodu. Stručně řečeno se zavádí pomocí klíčového slova <code>class</code>, a to jako úplně „čisté“ (dědí pouze po obecném objektu <em>Object</em>)..
  </p>
  <example lang="python">
    class MojeTřída:
        pass
  </example>
  <p>
    ..nebo jako potomci jiných tříd, jako třeba zde naše vlastní varianta obecné výjimky:
  </p>
  <example lang="python">
    class MojeChyba(Exception):
        pass
  </example>

</slide>
<slide title="„Magické“ atributy tříd">

  <p>
    Třídy, podobně jako funkce, jsou v Python'u velmi mocné, ale trochu jiným způsobem, než je člověk zvyklý z čistě a prvoplánově OOP-jazyků.
  </p>
  <p>
    Přitom prakticky všechno, na co si můžete v Python'u „šáhnout“, je nějakým způsobem objekt (instance nějaké třídy). Nepřekvapí proto, že Python poskytuje poměrně mocný aparát pro úpravu chování objektů. Většina této funkcionality je schována ve speciálních <em>dvoupodtržítkových</em> atributech.
  </p>
  <note>
    Python nerozeznává koncepci soukromých, privátních atributů. Ale atributy, jejichž <em>jméno začíná alespoň dvěma podtržítky a končí podtržítkem nejvýše jedním</em> se budou jako privátní tvářit – nejsou totiž na třídě (ani instanci) pod tímto jménem dostupné. (Pokud ovšem víte, že tam jsou, stejně se k nim dokážete dostat.)
  </note>
  <p>
    Pár ukázek:
  </p>
  <ul>
    <li>
        <example lang="python">__call__()</example>
        uvedené třídy (jejich instance) se budou chovat jako funkce (půjde je zavolat)
    </li>
    <li>
        <example lang="python">
            __enter__()
            __exit__()
        </example>
        uvedené třídy bude možné použít uvnitř bloku <em>with</em>
    </li>
    <li>
        <example lang="python">
            __len__()
            __contains__(x)
        </example>
        uvedené třídy se budou chovat jako množiny (tedy bude možné na ně aplikovat množinové operace)
    </li>
    <li>
        <example lang="python">
            __iter__()
            __next__()
            __reversed__()
        </example>
        uvedené třídy se budou chovat jako iterátory
    </li>
    <!--li>
        <example lang="python"></example>
        xxx
    </li-->
  </ul>
  <note>
    Více viz <a href="http://diveintopython3.ep.io/special-method-names.html" class="external">http://diveintopython3.ep.io/special-method-names.html</a>.
  </note>

</slide>
<slide title="„dir()“">
  
  <p>
    Snad nejužitečnější funkce v Python'u:
  </p>
  <example lang="python">
dir( OBJEKT )
  </example>
  <p>
    Příklad:
  </p>
  <example lang="python">
>>> dir( 'ahoj' )
['__add__', '__class__', '__contains__', '__delattr__', '__doc__', '__eq__', 
 '__ge__', '__getattribute__', '__getitem__', '__getnewargs__', '__getslice__', 
 '__gt__', '__hash__', '__init__', '__le__', '__len__', '__lt__', '__mod__', 
 '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', 
 '__rmod__', '__rmul__', '__setattr__', '__str__', 'capitalize', 'center', 
 'count', 'decode', 'encode', 'endswith', 'expandtabs', 'find', 'index', 
 'isalnum', 'isalpha', 'isdigit', 'islower', 'isspace', 'istitle', 'isupper', 
 'join', 'ljust', 'lower', 'lstrip', 'partition', 'replace', 'rfind', 'rindex', 
 'rjust', 'rpartition', 'rsplit', 'rstrip', 'split', 'splitlines', 'startswith', 
 'strip', 'swapcase', 'title', 'translate', 'upper', 'zfill']
  </example>
  
  <br/>
  
  <p>
    Typ <em>řetězec</em> má tedy následující atributy:
  </p>
  <ul>
    <li>
      „běžné“:
<pre>capitalize       isalpha           lstrip              split
center           isdigit           partition           splitlines
count            islower           replace             startswith
decode           isspace           rfind               strip
encode           istitle           rindex              swapcase
endswith         isupper           rjust               title
expandtabs       join              rpartition          translate
find             ljust             rsplit              upper
index            lower             rstrip              zfill
isalnum </pre>
    </li>
  </ul>
  <note>
    S těmito atributy se setkáte při běžné práci. <!--Mezi metodami objektu a datovými atributy můžete rozlišit např. pomocí vestavěné funkce <code>isinstance(ATRIBUT, collections.Calable)</code> . -->
  </note>
  <ul>
    <li>
      „magické“ (které vás nemusí ve většině případů zajímat):
<pre>__add__           __getattribute__           __le__           __reduce__
__class__         __getitem__                __len__          __reduce_ex__
__contains__      __getnewargs__             __lt__           __repr__
__delattr__       __getslice__               __mod__          __rmod__
__doc__           __gt__                     __mul__          __rmul__
__eq__            __hash__                   __ne__           __setattr__
__ge__            __init__                   __new__          __str__ </pre>
    </li>
  </ul>

</slide>


</lecture>
