N-tice

Když už známe seznam, podívejme se na jeho sestřičku: takzvanou n-tici (angl. tuple).

N-tice může, podobně jako seznam, obsahovat n prvků. N-tice se dvěma prvky je dvojice neboli pár (angl. pair); se třemi prvky trojice (angl. 3-tuple), se čtyřmi čtveřice (angl. 4-tuple), atd.

Pro úplnost: existují i n-tice s jedním prvkem (hmm… „jednice”?) a s nula prvky (prázdné n-tice, angl. empty tuple), ale ty nejsou příliš užitečné a v praxi se moc nepoužívají.

N-tice se tvoří jako seznamy, jen kolem sebe nemají hranaté závorky. Stačí čárky mezi prvky:

dvojice = 'Pat', 'Mat'
print(dvojice)

Chovají skoro stejně jako seznamy, jen nejdou měnit. Nemají tedy metody jako append a pop a nedá se jim přiřazovat do prvků. Dají se ale použít v cyklu for a dají se z nich číst jednotlivé prvky.

osoby = 'máma', 'teta', 'babička'
for osoba in osoby:
    print(osoba)

prvni = osoby[0]
print(f'První je {prvni}')

Vypadá to povědomě? Aby ne! N-tice jsme už použily dříve: for pozdrav in 'Ahoj', 'Hello', 'Ciao': ve skutečnosti používá n-tici!

Když chceš n-tici předat do funkce, narazíš na problém, že čárka odděluje jednotlivé argumenty funkce. V podobných případech musíš n-tici uzavřít do závorek, aby bylo jasné, že jde o jednu hodnotu (byť složenou).

seznam_dvojic = []
for i in range(10):
    # `append` bere jen jeden argument; dáme mu jednu dvojici
    seznam_dvojic.append((i, i**2))
print(seznam_dvojic)

N-tice se hodí, pokud chceš z funkce vrátit víc než jednu hodnotu. Prostě v příkazu return oddělíš vracené hodnoty čárkou. Vypadá to, že vracíš několik hodnot, ale ve skutečnosti se vrací jen jedna n-tice.

def podil_a_zbytek(a, b):
    return a // b, a % b

Funkci „podíl a zbytek“ je mimochodem k dispozici přímo v Pythonu pod jménem divmod.

Python umí ještě jeden trik, takzvané „rozbalení“: pokud chceš přiřadit do několika proměnných najednou, stačí je na levé straně rovnítka oddělit čárkou a na pravou stranu dát nějakou „složenou” hodnotu – třeba právě n-tici.

podil, zbytek = podil_a_zbytek(12, 5)

N-tice se k „rozbalování“ hodí nejvíc, protože mají daný počet prvků. Jde to ale použít se všemi hodnotami, které jdou použít ve for:

x, o = 'xo'
jedna, dva, tri = [1, 2, 3]

Malé n-tice

Jak vytvořit n-tici s žádným nebo jedním prvkem? Takhle:

prazdna_ntice = ()
jednoprvkova_ntice = ('a', )

Druhý příklad jde i bez závorek – jednoprvkova_ntice = 'a', – ale to vypadá jako zapomenutá čárka. Když budeš opravdu potřebovat jednoprvkovou n-tici, radši ji pro přehlednost ozávorkuj.

Kdy použít seznam a kdy n-tici?

Seznamy se používají, když předem nevíš, kolik v nich přesně bude hodnot, nebo když je hodnot mnoho. Například seznam slov ve větě, seznam účastníků soutěže, seznam tahů ve hře nebo seznam karet v balíčku. Oproti tomu for pozdrav in 'Ahoj', 'Hello', 'Hola', 'Hei', 'SYN': používá n-tici.

N-tice se často používají na hodnoty různých typů, kdy má každá „pozice” v n-tici úplně jiný význam. Například seznam můžeš použít na písmena abecedy, ale dvojice index–hodnota z enumerate je n-tice.

Prázdné n-tice a n-tice s jedním prvkem se zapisují trochu divně a má to své důvody: může-li nastat situace, kdy takovou sekvenci budeš potřebovat, většinou je lepší sáhnout po seznamu. Například seznam hracích karet v ruce nebo seznam lidí aktuálně přihlášených do soutěže může být občas prázdný.

Seznamy i n-tice mají i technické limity: n-tice nejdou měnit a až se naučíme pracovat se slovníky, zjistíme že seznamy tam nepůjdou použít jako klíče.

Často není úplně jasné, který typ použít – v takovém případě je to pravděpodobně jedno. Řiď se instinktem. :)

{
  "data": {
    "sessionMaterial": {
      "id": "session-material:2019/brno-podzim-pondeli:list:1",
      "title": "N-tice",
      "html": "\n          \n    \n\n    <h2><var>N</var>-tice</h2>\n<p>Kdy&#x17E; u&#x17E; zn&#xE1;me seznam, pod&#xED;vejme se na jeho sest&#x159;i&#x10D;ku: takzvanou\n<var>n</var>-tici (angl. <em>tuple</em>).</p>\n<p><var>N</var>-tice m&#x16F;&#x17E;e, podobn&#x11B; jako seznam, obsahovat <var>n</var> prvk&#x16F;. \n<var>N</var>-tice se dv&#x11B;ma prvky je <em>dvojice</em>\nneboli <em>p&#xE1;r</em> (angl. <em>pair</em>); se t&#x159;emi\nprvky <em>trojice</em> (angl. <em>3-tuple</em>),\nse &#x10D;ty&#x159;mi <em>&#x10D;tve&#x159;ice</em> (angl. <em>4-tuple</em>), atd.</p>\n<div class=\"admonition note\"><p>Pro &#xFA;plnost: existuj&#xED; i <var>n</var>-tice s&#xA0;jedn&#xED;m prvkem (hmm&#x2026; &#x201E;jednice&#x201D;?)\na s&#xA0;nula prvky (pr&#xE1;zdn&#xE9; <var>n</var>-tice, angl. <em>empty tuple</em>),\nale ty nejsou p&#x159;&#xED;li&#x161; u&#x17E;ite&#x10D;n&#xE9; a v&#xA0;praxi se moc nepou&#x17E;&#xED;vaj&#xED;.</p>\n</div><p><var>N</var>-tice se tvo&#x159;&#xED; jako seznamy, jen kolem sebe nemaj&#xED; hranat&#xE9; z&#xE1;vorky.\nSta&#x10D;&#xED; &#x10D;&#xE1;rky mezi prvky:</p>\n<div class=\"highlight\"><pre><span></span><span class=\"n\">dvojice</span> <span class=\"o\">=</span> <span class=\"s1\">&apos;Pat&apos;</span><span class=\"p\">,</span> <span class=\"s1\">&apos;Mat&apos;</span>\n<span class=\"k\">print</span><span class=\"p\">(</span><span class=\"n\">dvojice</span><span class=\"p\">)</span>\n</pre></div><p>Chovaj&#xED; skoro stejn&#x11B; jako seznamy, jen nejdou m&#x11B;nit.\nNemaj&#xED; tedy metody jako <code>append</code>\na <code>pop</code> a ned&#xE1; se jim p&#x159;i&#x159;azovat do prvk&#x16F;.\nDaj&#xED; se ale pou&#x17E;&#xED;t v cyklu <code>for</code>\na daj&#xED; se z&#xA0;nich &#x10D;&#xED;st jednotliv&#xE9; prvky.</p>\n<div class=\"highlight\"><pre><span></span><span class=\"n\">osoby</span> <span class=\"o\">=</span> <span class=\"s1\">&apos;m&#xE1;ma&apos;</span><span class=\"p\">,</span> <span class=\"s1\">&apos;teta&apos;</span><span class=\"p\">,</span> <span class=\"s1\">&apos;babi&#x10D;ka&apos;</span>\n<span class=\"k\">for</span> <span class=\"n\">osoba</span> <span class=\"ow\">in</span> <span class=\"n\">osoby</span><span class=\"p\">:</span>\n    <span class=\"k\">print</span><span class=\"p\">(</span><span class=\"n\">osoba</span><span class=\"p\">)</span>\n\n<span class=\"n\">prvni</span> <span class=\"o\">=</span> <span class=\"n\">osoby</span><span class=\"p\">[</span><span class=\"mi\">0</span><span class=\"p\">]</span>\n<span class=\"k\">print</span><span class=\"p\">(</span><span class=\"n\">f</span><span class=\"s1\">&apos;Prvn&#xED; je {prvni}&apos;</span><span class=\"p\">)</span>\n</pre></div><div class=\"admonition note\"><p>Vypad&#xE1; to pov&#x11B;dom&#x11B;? Aby ne!\n<var>N</var>-tice jsme u&#x17E; pou&#x17E;ily d&#x159;&#xED;ve:\n<code>for pozdrav in &apos;Ahoj&apos;, &apos;Hello&apos;, &apos;Ciao&apos;:</code>\nve skute&#x10D;nosti pou&#x17E;&#xED;v&#xE1; <var>n</var>-tici!</p>\n</div><p>Kdy&#x17E; chce&#x161; <var>n</var>-tici p&#x159;edat do funkce,\nnaraz&#xED;&#x161; na probl&#xE9;m, &#x17E;e &#x10D;&#xE1;rka odd&#x11B;luje jednotliv&#xE9;\nargumenty funkce.\nV&#xA0;podobn&#xFD;ch p&#x159;&#xED;padech mus&#xED;&#x161; <var>n</var>-tici\nuzav&#x159;&#xED;t do z&#xE1;vorek, aby bylo jasn&#xE9;, &#x17E;e jde o jednu\nhodnotu (by&#x165; slo&#x17E;enou).</p>\n<div class=\"highlight\"><pre><span></span><span class=\"n\">seznam_dvojic</span> <span class=\"o\">=</span> <span class=\"p\">[]</span>\n<span class=\"k\">for</span> <span class=\"n\">i</span> <span class=\"ow\">in</span> <span class=\"nb\">range</span><span class=\"p\">(</span><span class=\"mi\">10</span><span class=\"p\">):</span>\n    <span class=\"c1\"># `append` bere jen jeden argument; d&#xE1;me mu jednu dvojici</span>\n    <span class=\"n\">seznam_dvojic</span><span class=\"o\">.</span><span class=\"n\">append</span><span class=\"p\">((</span><span class=\"n\">i</span><span class=\"p\">,</span> <span class=\"n\">i</span><span class=\"o\">**</span><span class=\"mi\">2</span><span class=\"p\">))</span>\n<span class=\"k\">print</span><span class=\"p\">(</span><span class=\"n\">seznam_dvojic</span><span class=\"p\">)</span>\n</pre></div><p><var>N</var>-tice se hod&#xED;, pokud chce&#x161; z&#xA0;funkce vr&#xE1;tit\nv&#xED;c ne&#x17E; jednu hodnotu.\nProst&#x11B; v p&#x159;&#xED;kazu <code>return</code> odd&#x11B;l&#xED;&#x161; vracen&#xE9; hodnoty &#x10D;&#xE1;rkou.\nVypad&#xE1; to, &#x17E;e vrac&#xED;&#x161; n&#x11B;kolik hodnot, ale\nve skute&#x10D;nosti se vrac&#xED; jen jedna <var>n</var>-tice.</p>\n<div class=\"highlight\"><pre><span></span><span class=\"k\">def</span> <span class=\"nf\">podil_a_zbytek</span><span class=\"p\">(</span><span class=\"n\">a</span><span class=\"p\">,</span> <span class=\"n\">b</span><span class=\"p\">):</span>\n    <span class=\"k\">return</span> <span class=\"n\">a</span> <span class=\"o\">//</span> <span class=\"n\">b</span><span class=\"p\">,</span> <span class=\"n\">a</span> <span class=\"o\">%</span> <span class=\"n\">b</span>\n</pre></div><div class=\"admonition note\"><p>Funkci &#x201E;pod&#xED;l a zbytek&#x201C; je mimochodem k&#xA0;dispozici p&#x159;&#xED;mo v&#xA0;Pythonu\npod jm&#xE9;nem <code>divmod</code>.</p>\n</div><p>Python um&#xED; je&#x161;t&#x11B; jeden trik, takzvan&#xE9; &#x201E;rozbalen&#xED;&#x201C;: pokud chce&#x161; p&#x159;i&#x159;adit\ndo n&#x11B;kolika prom&#x11B;nn&#xFD;ch najednou, sta&#x10D;&#xED; je na lev&#xE9;\nstran&#x11B; rovn&#xED;tka odd&#x11B;lit &#x10D;&#xE1;rkou a na pravou stranu\nd&#xE1;t n&#x11B;jakou &#x201E;slo&#x17E;enou&#x201D; hodnotu &#x2013; t&#x159;eba pr&#xE1;v&#x11B;\n<var>n</var>-tici.</p>\n<div class=\"highlight\"><pre><span></span><span class=\"n\">podil</span><span class=\"p\">,</span> <span class=\"n\">zbytek</span> <span class=\"o\">=</span> <span class=\"n\">podil_a_zbytek</span><span class=\"p\">(</span><span class=\"mi\">12</span><span class=\"p\">,</span> <span class=\"mi\">5</span><span class=\"p\">)</span>\n</pre></div><div class=\"admonition note\"><p><var>N</var>-tice se k&#xA0;&#x201E;rozbalov&#xE1;n&#xED;&#x201C; hod&#xED; nejv&#xED;c, proto&#x17E;e maj&#xED;\ndan&#xFD; po&#x10D;et prvk&#x16F;.\nJde to ale pou&#x17E;&#xED;t se v&#x161;emi hodnotami, kter&#xE9; jdou pou&#x17E;&#xED;t ve <code>for</code>:</p>\n<div class=\"highlight\"><pre><span></span><span class=\"n\">x</span><span class=\"p\">,</span> <span class=\"n\">o</span> <span class=\"o\">=</span> <span class=\"s1\">&apos;xo&apos;</span>\n<span class=\"n\">jedna</span><span class=\"p\">,</span> <span class=\"n\">dva</span><span class=\"p\">,</span> <span class=\"n\">tri</span> <span class=\"o\">=</span> <span class=\"p\">[</span><span class=\"mi\">1</span><span class=\"p\">,</span> <span class=\"mi\">2</span><span class=\"p\">,</span> <span class=\"mi\">3</span><span class=\"p\">]</span>\n</pre></div></div><h2>Mal&#xE9; <var>n</var>-tice</h2>\n<p>Jak vytvo&#x159;it <var>n</var>-tici s &#x17E;&#xE1;dn&#xFD;m nebo jedn&#xED;m prvkem? Takhle:</p>\n<div class=\"highlight\"><pre><span></span><span class=\"n\">prazdna_ntice</span> <span class=\"o\">=</span> <span class=\"p\">()</span>\n<span class=\"n\">jednoprvkova_ntice</span> <span class=\"o\">=</span> <span class=\"p\">(</span><span class=\"s1\">&apos;a&apos;</span><span class=\"p\">,</span> <span class=\"p\">)</span>\n</pre></div><p>Druh&#xFD; p&#x159;&#xED;klad jde i bez z&#xE1;vorek &#x2013;\n<code>jednoprvkova_ntice = &apos;a&apos;,</code> &#x2013;\nale to vypad&#xE1; jako zapomenut&#xE1; &#x10D;&#xE1;rka.\nKdy&#x17E; bude&#x161; <em>opravdu</em> pot&#x159;ebovat jednoprvkovou\n<var>n</var>-tici, rad&#x161;i ji pro p&#x159;ehlednost oz&#xE1;vorkuj.</p>\n<h2>Kdy pou&#x17E;&#xED;t seznam a kdy <var>n</var>-tici?</h2>\n<p>Seznamy se pou&#x17E;&#xED;vaj&#xED;, kdy&#x17E; p&#x159;edem nev&#xED;&#x161;,\nkolik v nich p&#x159;esn&#x11B; bude hodnot,\nnebo kdy&#x17E; je hodnot mnoho.\nNap&#x159;&#xED;klad seznam slov ve v&#x11B;t&#x11B;,\nseznam &#xFA;&#x10D;astn&#xED;k&#x16F; sout&#x11B;&#x17E;e, seznam tah&#x16F; ve h&#x159;e\nnebo seznam karet v bal&#xED;&#x10D;ku.\nOproti tomu <code>for pozdrav in &apos;Ahoj&apos;, &apos;Hello&apos;, &apos;Hola&apos;, &apos;Hei&apos;, &apos;SYN&apos;:</code>\npou&#x17E;&#xED;v&#xE1; <var>n</var>-tici.</p>\n<p><var>N</var>-tice se &#x10D;asto pou&#x17E;&#xED;vaj&#xED; na hodnoty\nr&#x16F;zn&#xFD;ch typ&#x16F;, kdy m&#xE1; ka&#x17E;d&#xE1; &#x201E;pozice&#x201D;\nv <var>n</var>-tici &#xFA;pln&#x11B; jin&#xFD; v&#xFD;znam.\nNap&#x159;&#xED;klad seznam m&#x16F;&#x17E;e&#x161; pou&#x17E;&#xED;t na p&#xED;smena abecedy,\nale dvojice index&#x2013;hodnota z&#xA0;<code>enumerate</code>\nje <var>n</var>-tice.</p>\n<p>Pr&#xE1;zdn&#xE9; <var>n</var>-tice a <var>n</var>-tice s jedn&#xED;m\nprvkem se zapisuj&#xED; trochu divn&#x11B; a m&#xE1; to sv&#xE9; d&#x16F;vody:\nm&#x16F;&#x17E;e-li nastat situace, kdy takovou sekvenci bude&#x161;\npot&#x159;ebovat, v&#x11B;t&#x161;inou je lep&#x161;&#xED; s&#xE1;hnout po seznamu.\nNap&#x159;&#xED;klad seznam hrac&#xED;ch karet v ruce nebo\nseznam lid&#xED; aktu&#xE1;ln&#x11B; p&#x159;ihl&#xE1;&#x161;en&#xFD;ch do sout&#x11B;&#x17E;e\nm&#x16F;&#x17E;e b&#xFD;t ob&#x10D;as pr&#xE1;zdn&#xFD;.</p>\n<p>Seznamy i n-tice maj&#xED; i technick&#xE9; limity:\n<var>n</var>-tice nejdou m&#x11B;nit a a&#x17E; se nau&#x10D;&#xED;me pracovat se slovn&#xED;ky,\nzjist&#xED;me &#x17E;e seznamy tam nep&#x16F;jdou pou&#x17E;&#xED;t jako kl&#xED;&#x10D;e.</p>\n<p>&#x10C;asto nen&#xED; &#xFA;pln&#x11B; jasn&#xE9;, kter&#xFD; typ pou&#x17E;&#xED;t\n&#x2013; v takov&#xE9;m p&#x159;&#xED;pad&#x11B; je to pravd&#x11B;podobn&#x11B; jedno.\n&#x158;i&#x10F; se instinktem. :)</p>\n\n\n        "
    }
  }
}