<?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>Seznamy</title>
  <date>2010-10-27</date>
  <link><!--a href="http://vyuka.ookami.cz" rel="external">http://vyuka.ookami.cz</a--></link>
</meta>
<!--
  „“–
  ↵ aneb &#x21B5; aneb \r aneb CR aneb CarriageReturn
-->


<slide title="Úvod">
  
  <p>
    Se seznamy se setkáme v Python'u úplně všude, málem stejně často jako s iterátory :) Je to jeden z nejdůležitějších sekvenčních typů – umožňuje schraňovat pohromadě libovolné (a proměnlivé) množství nejrůznějších objektů.
  </p>

</slide>
<slide title="Zavedení – „[]“ a „list()“">

  <p class="enumerate">
    Z daných objektů vytvoříme seznam nejsnadněji jejich uzavřením do hranatých závorek:
  </p>
  <example lang="python">
>>> xs = [ 'Ahoj!', 123, (12, 'tři'), ['hokus', 'pokus'], 'lokus 666' ]
>>> xs
['Ahoj!', 123, (12, 'tři'), ['hokus', 'pokus'], 'lokus 666']
  </example>
  
  <p class="enumerate">
    Kromě toho je možné za pomoci funkce <code>list()</code> převádět jiné typy na seznam, například řetězce:
  </p>
  <example lang="python">
>>> xs = "Ahoj, světe!"
>>> xs
'Ahoj, světe!'
>>> list(xs)
['A', 'h', 'o', 'j', ',', ' ', 's', 'v', 'ě', 't', 'e', '!']
  </example>

</slide>
<slide title="Prázdný seznam">

  <p>
    <strong>Prázdný seznam</strong> můžeme zavést dvěma různými zůsoby – buď pomocí funkce <code>list()</code> nebo přímou notací:
  </p>
  <example lang="python">
>>> xs = list()
>>> xs
[]

>>> xs = []
>>> xs
[]

>>> type(xs)
&lt;class 'list'>
  </example>

</slide>
<slide title="Seznamy jako sekvence">

  <p>
    Jelikož seznamy patří mezi sekvence, máme k dispozici celou armádu sekvenčních operací:
  </p>
  <example lang="python">
>>> xs = ['Ahoj!', 123, (12, 'tři'), ['hokus', 'pokus'], 'lokus 666']

# délka sekvence
>>> len(xs)
5

# konkrétní prvek
>>> xs[3]
['hokus', 'pokus']
>>> xs[-3]
(12, 'tři')

# různé výřezy
>>> xs[1:3]
[123, (12, 'tři')]
>>> xs[1::2]
[123, ['hokus', 'pokus']]
>>> xs[3:]
[['hokus', 'pokus'], 'lokus 666']
>>> xs[-3:]
[(12, 'tři'), ['hokus', 'pokus'], 'lokus 666']

# dotaz na výskyt prvku
>>> 123 in xs
True
>>> (12, 'tři') in xs
True
>>> 'fokus' in xs
False

# dvě spojené kopie
>>> xs * 2
['Ahoj!', 123, (12, 'tři'), ['hokus', 'pokus'], 'lokus 666', 'Ahoj!', 123, (12, 'tři'), ['hokus', 'pokus'], 'lokus 666']
  </example>
  <note>
    Komentáře zde pochopitelně nejsou součástí výstupu interaktivního interpretru, slouží pouze k popisu zde zapsaného kódu.
  </note>

</slide>
<slide title="Seznamy jako sekvence – smyčka „for-in“">

  <p class="enumerate">
    Po seznamech se pak přirozeně prochází smyčkou, pro libovolné typy prvků ve třech základních podobách:
  </p>
  <example lang="python">
>>> xs = ['Ahoj!', 123, (12, 'tri'), ['hokus', 'pokus'], 'lokus 666']

>>> for x in xs:
...     print(x)
...
Ahoj!
123
(12, 'tři')
['hokus', 'pokus']
lokus 666

>>> for (i, x) in enumerate(xs):
...     print(i, x)
...
0 Ahoj!
1 123
2 (12, 'tři')
3 ['hokus', 'pokus']
4 lokus 666

>>> for x in reversed(xs):
...   print(x)
...
lokus 666
['hokus', 'pokus']
(12, 'tri')
123
Ahoj!
  </example>
  
  <p class="enumerate">
    Poslední variantu – řazení prvků pomocí funkce <em>sorted()</em> – však můžeme použít pouze tehdy, jsou-li jednotlivé <strong>prvky porovnatelné</strong> (což typicky znamená <em>stejného typu</em>, zde ukázáno na celých číslech, ale není to nutně pravda):
  </p>
  <example lang="python">
>>> xs = [5, 2, 3, 1, 4]
>>> for x in sorted(xs):
...   print(x)
...
1
2
3
4
5
  </example>

</slide>
<slide title="Seznamy jako měnitelné sekvence">

  <p>
    Narozdíl např. od řetězců seznamy patří mezi sekvence <strong>měnitelné</strong> (<i>mutable</i>), což znamená, že jejich obsah po vytvoření můžeme libovolně upravovat:
  </p>
  <example lang="python">
>>> xs = ['Ahoj!', 123, (12, 'tři'), ['hokus', 'pokus'], 'lokus 666']

>>> xs[3]
['hokus', 'pokus']
>>> xs[3] = 'fokus'
>>> xs[3]
'fokus'
>>> xs
['Ahoj!', 123, (12, 'tři'), 'fokus', 'lokus 666']
  </example>
  <p>
    A to dokonce i po celých výřezech:
  </p>
  <example lang="python">
>>> xs = [1, 2, 3, 4, 5]
>>> xs[3:] = [666]
>>> xs
[1, 2, 3, 666]
  </example>
  <note>
    Jelikož nahrazujeme část seznamu (výřezová notace v tomto případě vrací seznam), Python očekává na vstupu zase seznam.
  </note>

</slide>
<slide title="Dotazování na prvky – „in“, „index()“, „count()“">
  
  <p class="enumerate">
    Kromě již dříve uvedeného a všem sekvencím společného operátoru <code>in</code>:
  </p>
  <example lang="python">
>>> xs = ['Ahoj!', 123, (12, 'tři'), ['hokus', 'pokus'], 'lokus 666']

>>> 123 in xs
True
>>> (12, 'tři') in xs
True
>>> 'fokus' in xs
False
  </example>
  
  <p class="enumerate">
    ...mají seznamy k dispozici i metodu <code>index(PRVEK)</code>, která slouží k navrácení pozice prvního výskytu prvku s uvedenou hodnotou:
  </p>
  <example lang="python">
>>> xs = ['jedna', 'dvě', 'tři', 'jedna', 'pět', 'šest', ]

>>> xs.index('jedna')
0
>>> xs.index('pět')
4
  </example>
  <note>
    Není-li takový prvek v seznamu k dispozici, obdržíme výjimku <em>ValueError</em>.
  </note>
  
  <p class="enumerate">
    Kromě toho můžeme i počítat výskyty zadaného prvku pomocí metody <code>count(PRVEK)</code>:
  </p>
  <example lang="python">
>>> xs = ['jedna', 'dvě', 'tři', 'jedna', 'pět', 'šest', ]

>>> xs.count('jedna')
2
>>> xs.count('dvě')
1
  </example>

</slide>
<slide title="Přidávání prvků – „append()“, „insert()“, „extend()“, „+=“, „=+“">
  
  <p>
    Přidat nové prvky do existující seznamu se dá celkem čtyřmi způsoby. Pro ukázku budeme pracovat nad počátečním seznamem <code>xs = [1, 2.0, 'tři']</code>:
  </p>

  <p class="enumerate">
    Předně můžeme využít metody seznamu <code>append(PRVEK)</code> pro přidání jednoho nového prvku na konec seznamu:
  </p>
  <example lang="python">
>>> xs.append('four')
>>> xs
[1, 2.0, 'tři', 'four']
  </example>
  <note>
    Ač to tak možná na první pohled nevypadá, ekvivalentní kód zařizující totéž jest: <code>xs[ len(xs): ] = ['four']</code>
  </note>

  <p class="enumerate">
    Jeden prvek také můžeme pomocí metody <code>insert(NA_KTERÝ_NOVÝ_INDEX, PRVEK)</code> (resp. <code>PŘED_KTERÝ_STARÝ_INDEX</code>) vložit na vybrané místo seznamu:
  </p>
  <example lang="python">
>>> xs.insert(3, 3.5)
>>> xs
[1, 2.0, 'tři', 3.5, 'four']
  </example>
  <notes>
    <note>
      Jinak řečeno: <code>xs.insert(0, x)</code> přidá prvek <em>x</em> na začátek seznamu, zatímco <code>xs.insert(len(xs), x)</code> na konec (takže provede to samé jako <code>xs.append(x)</code>).
    </note>
    <note>
      A funguje to i pro záporné indexy – ty se počítají klasicky od konce.
    </note>
  </notes>

  <p class="enumerate">
    Na konec seznamu můžeme také přidat více prvků seznamu jiného, a to buď pomocí metody <code>extend(SEZNAM)</code>:
  </p>
  <example lang="python">
>>> xs.extend( [5, 'šest'] )
>>> xs
[1, 2.0, 'tři', 3.5, 'four', 5, 'šest']
  </example>

  <p class="enumerate">
    ..nebo pomocí „obyčejného“ slepování sekvencí pomocí operátoru <code>+</code>:
  </p>
  <example lang="python">
>>> xs += ['sedm', 8.0, 9]
>>> xs
[1, 2.0, 'tři', 3.5, 'four', 5, 'šest', 'sedm', 8.0, 9]
  </example>
  <note>
    Takto „přičíst“ se dá všelicos, třebas i n-tice nebo slovník. Pozor však na to, že přidávaná sekvence je <strong>proiterována prvek po prvku</strong> a takto prvek po prvku přidána do prvního seznamu:
    <example lang="python">
        >>> xs = [1, 2, 3, 4, 5]
        >>> xs += {6, 7, 8, 9}
        >>> xs
        [1, 2, 3, 4, 5, 8, 9, 6, 7]
    </example>
  </note>
  <!--note>
    Pro "=+" je z technického hlediska je nejdříve v paměti vytvořen nový dočasný seznam, do nějž jsou oba počáteční seznamy (tj. zde <em>xs</em> a <em>['sedm', 8.0, 9]</em>) „slepeny“, a teprve potom je tento přiřazen zpět identifikátoru <em>xs</em>. Vadit by vám to asi mohlo, kdyby slučované seznamy byly extrémně veliké. Narozdíl od toho "+=" se snaží dělat veškeré změny v místě. Proměnné objekty si typicky alokují větší místo, takže zřejmě dokud se nepřekročí volná hranice, nijak se to komplikovat nebude.
    PS: Vyzkoušet id().
  </note-->

</slide>
<slide title="„append()“ versus „extend()“">

  <p>
    Pozor na rozdíl mezi <code>append()</code> a <code>extend()</code>:
  </p>
  <example lang="python">
>>> xs = [1, 2, 3]
>>> xs
[1, 2, 3]

>>> xs.append( [4, 5, 6] )
>>> xs
[1, 2, 3, [4, 5, 6]]
>>> len(xs)
4
  </example>
  <p>
    versus
  </p>
  <example lang="python">
>>> xs = [1, 2, 3]
>>> xs
[1, 2, 3]

>>> xs.extend( [4, 5, 6] )
>>> xs
[1, 2, 3, 4, 5, 6]
>>> len(xs)
6
  </example>

</slide>
<slide title="Odebírání prvků – „del“, „pop()“, „remove()“">
  
  <p>
    Odebrat prvky ze seznamu se dá několika způsoby. Pro ukázku budeme pracovat nad počátečním seznamem <code>xs = ['jedna', 'dvě', 'tři', 'čtyři', 'pět', 'šest']</code>:
  </p>

  <p class="enumerate">
    Odebrat prvek, resp. prvky, na základě jeho, resp. jejich, pozice (indexu) nám umožňuje univerzální příkaz <code>del</code>:
  </p>
  <example lang="python">
>>> del xs[1]
>>> xs
['jedna', 'tři', 'čtyři', 'pět', 'šest']

>>> del xs[3:]
>>> xs
['jedna', 'tři', 'čtyři']
  </example>
  <note>
    Stačí tedy pomocí výřezové notace označit, čeho se chceme zbavit, a <em>del</em> se již postará o ostatní.
  </note>

  <p class="enumerate">
    Pro jeden prvek víceméně totéž zařídí metoda seznamu <code>pop([INDEX])</code>. Rozdíl je v tom, že odebraný prvek je metodou vrácen:
  </p>
  <example lang="python">
>>> xs = ['jedna', 'dvě', 'tři', 'čtyři', 'pět', 'šest']

>>> xs.pop()    # odstraň poslední prvek
'šest'
>>> xs
['jedna', 'dvě', 'tři', 'čtyři', 'pět']

>>> xs.pop(0)   # odstraň první prvek
'jedna'
>>> xs
['dvě', 'tři', 'čtyři', 'pět']

>>> xs.pop(2)   # odstraň prvek na pozici 2, tj. třetí
'čtyři'
>>> xs
['dvě', 'tři', 'pět']
  </example>
  <notes>
    <note>
      Pokus o odstranění prvku na neexistující pozici nebo z prázdného seznamu skončí výjimkou <em>IndexError</em>.
    </note>
    <note>
      Možná trošku překvapivě <code>pop(-1)</code> je opravdu ekvivalentem pro <code>pop()</code>.
    </note>
  </notes>

  <p class="enumerate">
    Poslední možností je odstranit prvek na základě jeho obsahu, a nikoli indexu. O to se stará metoda <code>remove(PRVEK)</code>. Odstraněn je vždy první výskyt daného prvku:
  </p>
  <example lang="python">
>>> xs = ['jedna', 'dvě', 'tři', 'dvě', 'pět', 'šest']

>>> xs.remove('dvě')
>>> xs
['jedna', 'tři', 'dvě', 'pět', 'šest']
  </example>
  <note>
    Pokus o odstranění prvku, který se v seznamu nenachází, skončí výjimkou <em>ValueError</em>.
  </note>

</slide>
<slide title="Řazení – metoda „reverse()“">
  
  <p>
    Prvky seznamu můžeme „otočit“, tj. zaměnit jejich pořadí od posledního k prvnímu, metodou <code>reverse()</code>:
  </p>
  <example lang="python">
>>> xs = [1, 2, 3, 4, 5, 6]
>>> xs
[1, 2, 3, 4, 5, 6]

>>> xs.reverse()
>>> xs
[6, 5, 4, 3, 2, 1]
  </example>
  <p>
    Metoda <code>reverse()</code> operuje nad aktuálním seznamem, tj. nic nevrací (resp. vrací hodnotu <em>None</em>), protože zamění pořadí prvků rovnou v seznamu, na kterém ji zavoláte! Její použití je z hlediska zachování dat ale neškodné, protože její další aplikace vše vrátí do původního stavu. Podle potřeby ale samozřejmě stačí použít globální funkci <code>reversed()</code>.
  </p>

</slide>
<slide title="Řazení – metoda „sort()“">

  <p>
    Skutečné setřídění prvků seznamu (lexikografické) se pak dá udělat buď také přímo v místě (takže ztratíme původní uspořádání) pomocí metody <code>sort([key[, reverse]])</code> nebo na kopii seznamu pomocí funkce <code>sorted()</code>:
  </p>
  <example lang="python">
>>> xs = ['jedna', 'dvě', 'tři', 'čtyři', 'pět', 'šest', 'sedm']

>>> xs.sort()
>>> xs
['dvě', 'jedna', 'pět', 'sedm', 'tři', 'čtyři', 'šest']
  </example>
  <note>
    Výchozí třídění řetězců probíhá porovnáváním unicodových <em>code-points</em> a česká nabodeníčka jsou holt až za ASCII-prvky…
  </note>
  
  <p class="enumerate">
    Metoda <em>sort()</em> (a funkce <em>sorted()</em> také) navíc akceptuje na vstupu parametr <em>reverse</em> signalizující třídění v opačném směru:
  </p>
  <example lang="python">
>>> xs = [3, 2, 7, 6, 1, 5]
>>> sorted(xs)
[1, 2, 3, 5, 6, 7]
>>> sorted(xs, reverse=True)
[7, 6, 5, 3, 2, 1]
  </example>

  <p class="enumerate">
    Posledním – a veskrze „magickým“ :) – parametrem je parametr <em>key</em>, který slouží (v podobě funkce jednoho argumentu) k určení porovnávacího klíče nad prvky seznamu:
  </p>
  <example lang="python">
>>> names = [ "John", "Wendy", "Pete", "Jane", "David", "Amanda", "Ix"]

# setřídění podle délky prvků
# ~ třídění je <em>stable</em>, takže zachová původní pořadí prvků se stejnou délkou
>>> sorted(names, key=len)
['Ix', 'John', 'Pete', 'Jane', 'Wendy', 'David', 'Amanda']
  </example>
  <p>
    Problematika parametru <em>key</em> a řazení vůbec je však dosti obsáhlá, a proto je jí věnována <a href="/materialy/python/sorting/overview.xml">samostatná kapitola</a>.
  </p>

</slide>
<slide title="Generátorová notace I">
  
  <note>
    Po vzoru Petra Přikryla, překladatele úžasné knihy Marka Pilgrima <a href="http://diveintopython3.net">Dive Into Python 3</a><!--a href="http://diveintopython3.org">Dive Into Python 3</a-->, budu podle aktuálního použití překládat anglický termín <em>list comprehension</em> někdy jako „generátorová notace (seznamu)“, jindy jako „generátor seznamu“ a ještě jindy i jako „generovaný seznam“.
  </note>
  
  <p>
    Bezesporu jednou z nejúžasnějších „zkratek“, které nám Python nabízí, je <em>generátorová notace</em> (nejen) seznamu. Umožňuje nám často velmi elegantně a na minimu prostoru vytvořit z původního seznamu seznam nový, který se skládá třeba i z úplně nových prvků, vytvořených však na základě prvků seznamu původního a dodatečných pravidel.
  </p>
  
  <p>
    Obecný konstruktor pro jednoduchý generátor seznamu vypadá takto:
  </p>
  <example lang="python">
    [ Funkce(I) for I in SEKVENCE ]
    [ Funkce(I) for I in SEKVENCE if PODMÍNKA ]
  </example>
  <notes>
    <note>
        Zatímco první varianta „pouze“ transformuje prvky vstupní sekvence na prvky výstupního seznamu, varianta druhá navíc ještě vybírá, pro které všechny prvky se tato transformace provede.
    </note>
    <note>
        Ve skutečnosti nemusí mít generovaná hodnota (v popisu jako <em>Funkce(I)</em>) se základní sekvencí <em>I</em> vůbec nic společného. Spíše jde o to, že výše popsané je zdaleka nejčastější využití generátoru seznamu.
    </note>
  </notes>

</slide>
<slide title="Generátorová notace II">

  <p>
    Spíše než složité vysvětlování několik snad názorných ukázek:
  </p>
  <example lang="python">
>>> xs = list( range(10) )
>>> xs
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

# kopie seznamu
>>> [x for x in xs]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

# každý prvek seznamu zvětšený o tři
>>> [x+3 for x in xs]
[3, 4, 5, 6, 7, 8, 9, 10, 11, 12]

# seznam druhých mocnin prvků původního seznamu
>>> [x*x for x in xs]
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

# výběr sudých prvků
>>> [x for x in xs if x % 2 == 0]
[0, 2, 4, 6, 8]

# seznam n-tic, kde je každý prvek přítomen jako číslo a zároveň i jako řetězec
>>> [(x, str(x)) for x in xs]
[(0, '0'), (1, '1'), (2, '2'), (3, '3'), (4, '4'), (5, '5'), (6, '6'), (7, '7'), (8, '8'), (9, '9')]

# jako předchozí, ale pouze pro liché prvky z původního seznamu
>>> [(x, str(x)) for x in xs if x % 2 != 0]
[(1, '1'), (3, '3'), (5, '5'), (7, '7'), (9, '9')]
  </example>

</slide>
<slide title="Generátorová notace III">

  <p>
    Sice už jsem to říkal, ale generovaný seznam nemusí mít s původním mnoho společného:
  </p>
  <example lang="python">
>>> [1 for x in "aeiou"]
[1, 1, 1, 1, 1]

>>> [i for i,x in enumerate("aeiou")]
[0, 1, 2, 3, 4]

>>> ds = {
...   'a': 'Haf!',
...   'e': 3,
...   'i': (1, 2, 3),
...   'o': list('abcd'),
...   'u': len,
... }
>>> [ds[x] for x in "aeiou"]
['Haf!', 3, (1, 2, 3), ['a', 'b', 'c', 'd'], &lt;built-in function len>]
  </example>

</slide>
<slide title="Vícenásobná generátorová notace">
  
  <p>
    Vícenásobná generátorová notace už nevypadá tak průhledně a ne vždy dělá to, co by člověk na první pohled hádal:
  </p>
  <example lang="python">
>>> vec1 = [2, 4, 6]
>>> vec2 = [4, 3, -9]

# pro každý prvek první smyčky bude znovu vykonána celá smyčka druhá
>>> [x*y for x in vec1 for y in vec2]
[8, 6, -18, 16, 12, -36, 24, 18, -54]

# z tohohle by se dal vytěžit skalární součin
>>> [vec1[i]*vec2[i] for i in range(len(vec1))]
[8, 12, -54]
  </example>
  <note>
    Převzato z dokumentace k Python'u.
  </note>
  
  <hr/>
  
  <p>
    Ještě poměrně průhledný, i když dosti šílený způsob jak najít prvočísla menší než 50:
  </p>
  <example lang="python">
>>> noprimes = [j for i in range(2, 8) for j in range(i*2, 50, i)]
>>> noprimes
[4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 6, 9, 12, 15, 18, 21, 24, 27, 30, 33, 36, 39, 42, 45, 48, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 10, 15, 20, 25, 30, 35, 40, 45, 12, 18, 24, 30, 36, 42, 48, 14, 21, 28, 35, 42, 49]

>>> primes = [x for x in range(2, 50) if x not in noprimes]
>>> primes
[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47]
  </example>
  <p>
    A jelikož se generátory seznamu dají zanořovat do sebe...
  </p>
  <example lang="python">
>>> [x for x in range(2, 50) if x not in [j for i in range(2, 8) for j in range(i*2, 50, i)]]
[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47]
  </example>
  <note>
    <a href="http://www.secnetix.de/olli/Python/list_comprehensions.hawk" class="external">http://www.secnetix.de/olli/Python/list_comprehensions.hawk</a>
  </note>

</slide>
<slide title="Použití seznamů">
  
  <p>
    Nepřekvapivě se pythoní seznamy používají především na místě jinde obvyklých polí, ale bez jejich omezení na předem známou délku a jeden jediný konkrétní typ.
  </p>
  <p>
    Přímo s pomocí vestavěných metod můžeme snadno implementovat datové struktury <a href="?slajd=18">fronty</a> a <a href="?slajd=17">zásobníku</a>, ale v podobě několika dalších modulů jsou k dispozici i mnohem specifičtější a v některých ohledech též tradičnější další datové struktury:
  </p>
  <ul>
    <li> typ <a href="/materialy/python/types.plus/deques.xml"><code>collections.deque</code></a> – oboustranná fronta; </li>
    <li> modul <a href="/materialy/python/types.plus/arrays.xml"><code>array</code></a> – číselná typovaná pole; </li>
    <li> modul <a href="/materialy/python/types.plus/bisects.xml"><code>bisect</code></a> – stále utříděné seznamy. </li>
  </ul>

</slide>
<slide title="Příklad – zásobník">
  
  <p>
    S dostupnými metodami proměníte seznam velmi snadno v <em>zásobník</em>, tedy paměťovou strukturu, kde poslední přidaný prvek je také první vrácený (<em>LIFO</em>). Příklad přímo z dokumentace:
  </p>
  <example lang="python">
>>> stack = [3, 4, 5]

>>> stack.append(6)
>>> stack.append(7)
>>> stack
[3, 4, 5, 6, 7]

>>> stack.pop()
7
>>> stack
[3, 4, 5, 6]

>>> stack.pop()
6
>>> stack.pop()
5
>>> stack
[3, 4]
  </example>

</slide>
<slide title="Příklad – fronta">
  
  <p>
    Téměř stejně jednoduše jako zásobník můžete naimplementovat i <em>frontu</em>, tedy paměťovou strukturu, kde první přidaný prvek je také první vrácený (<em>FIFO</em>). Příklad přímo z dokumentace:
  </p>
  <example lang="python">
>>> queue = ["Eric", "John", "Michael"]

>>> queue.append("Terry")           # Terry arrives
>>> queue.append("Graham")          # Graham arrives
>>> queue.pop(0)
'Eric'
>>> queue.pop(0)
'John'
>>> queue
['Michael', 'Terry', 'Graham']
  </example>

</slide>
<slide title="Vícenásobné seznamy">

  <p>
    Jelikož prvky seznamu může být cokoliv, snadno vyrobíme obdobu vícerozměrného pole:
  </p>
  <example lang="python">
>>> xs = [
...   [1, 2, 3],
...   [4, 5, 6],
...   [7, 8, 9],
... ]
>>> xs[1]
[4, 5, 6]
>>> xs[1][2]
6
  </example>
  <p>
    PS: Pro čistě číselná pole je samozřejmě lepší použít modul <a href="/materialy/python/types.plus/arrays.xml"><code>array</code></a> nebo rovnou balíček <a href="http://numpy.org" class="external"><em>numpy</em></a>.
  </p>

</slide>
  

</lecture>
