Data, datové typy a proměnné

O čem si budeme povídat?

Úvod

Při jakékoliv kreativní tvorbě potřebujeme tři základní položky: nástroje, suroviny a techniky (postupy). Když si například budeme chtít něco namalovat, našimi nástroji budou štětce, tužky a paleta. Technikami budeme rozumět malování vlhkým do vlhkého, rozmývání, sprejování a podobně. A konečně surovinami budou barvy, papír a voda. Podobné je to, když programujeme. Našimi nástroji jsou programovací jazyky, operační systémy a hardware. Za techniky budeme považovat používání programových konstrukcí, o kterých jsme se zmínili v předchozí části (Koncepty — Co je to programování?Společné vlastnosti programů). Surovinami budou data, se kterými budeme manipulovat. V této kapitole se zaměříme právě na tyto suroviny.

Tato kapitola je docela dlouhá a ze své podstaty poněkud nezáživná. Dobrá zpráva je, že si ji nemusíte přečíst celou najednou. Kapitola začíná pohledem na nezákladnější datové typy, které máme k dispozici. Dále si řekneme něco o tom, jak zacházet s kolekcemi položek. A nakonec se podíváme na některá pokročilejší témata. Čtení kapitoly můžete přerušit po přečtení části o kolekcích. Poté si můžete přečíst několik dalších kapitol a dočíst ji můžete v okamžiku, když začneme používat složitější věci.

Data

Pojem data je jedním z těch, který lidé často používají, ale málokdo rozumí jeho přesnému významu. V mém slovníku je pojem data definován takto:

"fakta nebo údaje, ze kterých je možné odvodit závěry; informace"

Příliš nám to sice nepomůže, ale tuto definici můžeme použít alespoň jako odrazový můstek. Uvidíme, zda se věci neozřejmí, když se podíváme na to, jak je pojem data používán v oblasti programování. Data jsou oním materiálem, surovými informacemi, se kterými manipuluje váš program. Bez dat nemůže program provádět žádnou užitečnou činnost. Programy mohou s daty manipulovat různými způsoby. Často to závisí na typu dat. S každým datovým typem je spojena skupina operací — tj. činností, které lze s daty daného typu provést. Tak například jsme si ukázali, že můžeme sčítat čísla. Sčítání je operace, kterou můžeme použít pro data typu číslo. Datových typů může být velké množství. Postupně se podíváme na nejběžnější z nich a na operace, které lze pro ně použít.

Proměnné

Data jsou uložena v paměti vašeho počítače. Můžeme ji přirovnat k velké stěně plné skříněk, která se na poštách používá k třídění poštovních zásilek. Dopis můžete strčit do libovolné skříňky, ale pokud by na těchto skříňkách nebyly štítky s konkrétní cílovou adresou, nedávalo by jejich použití smysl. Proměnné přestavují ty popisné štítky[1] na skříňkách a ony skříňky jsou vytvořeny v paměti vašeho počítače.

Zatím tedy víme, jak data vypadají. To je sice pěkné, ale k tomu, abychom s nimi mohli manipulovat, musíme být schopni se k nim dostat. Právě k tomuto účelu se používají proměnné. V programátorské terminologii říkáme, že vytváříme instance datových typů a přiřazujeme je do proměnných[2]. Proměnná představuje odkaz (nebo jinými slovy referenci) na určitou oblast, která leží někde v paměti počítače. V těchto paměťových oblastech jsou data uložena. V některých počítačových jazycích musí proměnná odpovídat typu dat, na která odkazuje. Jakýkoliv pokus o přiřazení chybného typu dat do takové proměnné způsobí ohlášení chyby. Někteří programátoři dávají takovým jazykům přednost — říká se jim jazyky se statickou typovou kontrolou[3] — protože umožňují předcházet určitým záludným chybám, které se obtížně hledají.

V jazyce Python proměnná získává typ podle do ní přiřazených dat. Datový typ si tato proměnná zapamatuje a pokud se pokusíte kombinovat data různého typu nedovoleným způsobem — jako je například sčítání řetězce a čísla —, budete varováni. (Vzpomínáte si na dříve uvedený příklad s chybovým hlášením? Ten byl příkladem právě takového typu chyby.) Pokud později proměnné přiřadíte data jiného typu, pak se typ proměnné změní. (To není například u výše zmíněných jazyků se statickou typovou kontrolou možné.)

>>> q = 7       # v q je nyní číslo
>>> print q
7
>>> q = "Sedm"  # do q jsme přiřadili řetězec
>>> print q
Sedm

Povšimněte si, že na začátku byl proměnné q přiřazen odkaz na číslo 7. V proměnné se hodnota odkazu udržovala až do té doby, než jsme ji přinutili, aby ukazovala na řetězec "Sedm". Takže ještě jednou: proměnné jazyka Python si uchovávají typ dat, na která ukazují. Ale to, na co ukazují, můžeme změnit jednoduše dalším přiřazením do této proměnné. V tomto okamžiku jsou původní data prohlášena za 'ztracená' a Python je odstraní z paměti (pokud na ně současně neodkazuje jiná proměnná). Tento proces je znám jako garbage collection. (Poznámka překladatele: Čti gábidž kolekšn. Tento pojem je natolik specifický, že se obvykle nepřekládá; doslova by se dal přeložit jako sbírání smetí.)

Garbage collection můžeme přirovnat k činnosti poštovního úředníka, který jednou a čas odstraní všechny dopisy a balíčky ze skříněk, které nemají žádný nápis. Pokud tyto dopisy na sobě nemají cílovou adresu nebo adresu odesílatele, hodí je do smetí.

Proměnné v jazycích VBScript a JavaScript

Při používání proměnných v jazycích VBScript a JavaScript se navíc setkáváme s drobnou odlišností. Oba uvedené jazyky vyžadují, abychom proměnnou před jejím použitím deklarovali. Jde o obecný rys, se kterým se setkáme u kompilovaných jazyků a u jazyků se silnou typovou kontrolou. Jednou z velkých výhod tohoto přístupu je to, že překladač může odhalit pokus o použití neznámé proměnné. K této situaci může dojít tím, že se při zápisu použití proměnné dopustíme překlepu v jejím jméně. Nevýhodou je samozřejmě to, že programátor toho musí napsat o něco víc.

Poznámka překladatele: Uvedená nevýhoda je zanedbatelná tím více, čím větší projekt se realizuje. V takových případech programátor věnuje mnohem více úsilí ostatním věcem, než je jednoduché klapání do klávesnice. Za skutečnou nevýhodu můžeme považovat nutnost deklarace proměnných pouze u jazyků, kde musíme deklaraci uvést na výrazně jiném místě zdrojového textu, než se objevuje její první použití. (Při pohledu do zdrojového textu — typicky přes okno editoru s omezeným počtem řádků na obrazovce — může programátor ztratit přehled o deklaraci proměnné. Musí ji dohledávat a ztrácí tím část svého času a mentální kapacity.) Příkladem takového jazyka je například jazyk C. Naproti tomu například modernější jazyk C++ dovoluje uvést deklaraci přímo v místě prvního použití proměnné.

Zajímavější diskusi lze vést na téma silná versus slabá typová kontrola. Donedávna se tradovalo, že silná typová kontrola je vždy a jednoznačně lepší, protože umožňuje odhalit určitou kategorii chyb již při překladu. V poslední době již nejsou názory tak vyhraněné. Silná typová může mít i nevýhody (komplikuje například generické programování) a navíc nezaručí odhalení jiné kategorie chyb — špatnou interpretaci hodnoty formálně správného typu. Odpovědi na tyto problémy se nyní nehledají pouze v technikách fungování překladačů, ale i v technologiích a technikách vývoje aplikací, v postupech programátorů. Jedním z přístupů, který prokázal svou užitečnost, je psaní testů funkčnosti (unit testing — jednotkové testy a acceptance testing — uživatelské testy). Poučení i zajímavé náměty k zamyšlení naleznete v článku Strong versus Weak Typing.

VBScript

Deklaraci proměnné zajistíme v jazyce VBScript použitím příkazu Dim, což je zkratka slova Dimension ([dajmenžn] = rozměr). Jde o projev dávných kořenů jazyka VBScript v jazyce BASIC a přes něj ještě dále v jazycích typu assembler. V těchto jazycích jste museli uvést, jak velký paměťový prostor bude proměnná vyžadovat — tedy její rozměr, velikost. Zkratka Dim se dochovala z těchto dob.

Deklarace proměnné v jazyce VBScript vypadá takto:

Dim promenna

Jakmile je proměnná jednou deklarována, můžeme ji používat stejně, jako jsme to ukázali u Pythonu. Jedním příkazem Dim můžeme deklarovat více proměnných. Jejich seznam oddělujeme čárkami:

Dim promenna, druha, treti

Přiřazení provedeme takto:

promenna = 42
druha = "Toto je krátká větička."
treti = 3.14159

Dalším klíčovým slovem, se kterým se můžete občas setkat, je Let ([let] = nechť). Jde opět o pozůstatek z jazyka BASIC a ve skutečnosti jej nemusíte vůbec používat. Pokud přesto někdy uvidíte jeho použití, bude vypadat nějak takto:

Let promenna = 22

V této učebnici nebudeme Let používat.

JavaScript

V jazyce JavaScript je deklarace proměnných uvedena klíčovým slovem var a v jedné deklaraci můžeme uvést více proměnných, jako v případě VBScript:

var promenna, druha, treti;

Součástí příkazu var může být v jazyce JavaScript i inicializace (nebo definice, tj. určení počáteční hodnoty) proměnných:

var promenna = 42;
var druha = "Krátká věta.", treti = 3.14159; 

Ušetříme tím trochu psaní, ale jinak se tato forma (funkčně) od dvoukrokové definice proměnných v jazyce VBScript nijak neliší.

Doufám, že tento stručný pohled proměnné v jazycích VBScript a JavaScript objasnil rozdíl mezi jejich deklarací a definicí. V jazyce Python dojde k deklaraci proměnné v okamžiku, kdy je uvedena její první definice.

Nyní se podívejme na příklady datových typů a uvidíme, jak to všechno pasuje dohromady.

Jednoduché datové typy

Jednoduché datové typy se nazývají jednoduchými proto, že patří k nejzákladnějším typům dat, se kterými se dá manipulovat. Složitější datové typy jsou ve skutečnosti jen kombinacemi jednoduchých datových typů. Jednoduché datové typy jsou stavebními kameny, ze kterých se ostatní typy budují. Jednoduché datové typy představují opravdový základ veškerých výpočtů. Patří k nim písmena, čísla a něco, čemu se říká boolovský typ (boolean).

Znakové řetězce

Už jsme se s nimi setkali. Patří k nim doslova libovolné řetězce, neboli posloupnosti znaků, které mohou být zobrazeny na vaší obrazovce. (Ve skutečnosti mohou obsahovat i netisknutelné řídicí znaky.)

V jazyce Python mohou být řetězce zapsány několika způsoby:

S jednoduchými apostrofy
'Toto je retezec'
S uvozovkami
"Toto je velmi podobny retezec"
S trojitými uvozovkami
"""Tady je velmi dlouhy retezec, ktery -- pokud
   si to budeme prat -- muze byt zapsan na vice 
   radcich. Python zachova viceradkovy retezec 
   ve tvaru, v jakem jej zapiseme..."""

Naposledy zmíněná forma má jedno speciální použití. Používá se k dokumentování funkcí, které jsme v jazyce Python sami napsali — k tomu se ještě dostaneme.

K jednotlivým znakům řetězce můžeme přistupovat jako ke složkám znakového pole (viz pole dále v textu). Každý programovací jazyk obvykle poskytuje operace pro manipulaci s řetězci — nalezni podřetězec, spoj dva řetězce, okopíruj jeden řetězec na jinam a podobné.

Za zmínku stojí skutečnost, že některé jazyky používají zvláštní typ pro ukládání znaků — tedy typ pro jeden znak. V takovém případě můžeme o řetězcích uvažovat jako o kolekcích hodnot typu znak. Ve srovnání s tímto přístupem Python používá pro uložení jednoho znaku jednoduše řetězec o délce jedna. To znamená, že nepotřebuje jiný syntaktický předpis pro zápis řetězce a jiný pro zápis jednoho znaku.

Řetězcové operátory

Nad řetězci lze provádět celou řadu operací. Některé z nich jsou přímo zabudovány do jazyka Pyhon, ale řada dalších je poskytována moduly, které musíme zapojit do činnosti příkazem import (tak, jak jsme to udělali s modulem sys v kapitole Jednoduché posloupnosti).

Řetězcové operátory
S1 + S2 Spojení řetězce S1 a S2
S1 * N N-násobné opakování řetězce S1

Následující příklady demonstrují jejich funkci:

>>> print 'Znovu a ' + 'znovu'        # spojení řetězců
Znovu a znovu
>>> print 'Opakuj ' * 3               # opakování řetězce
Opakuj Opakuj Opakuj
>>> print 'Znova ' + ('a znova ' * 3) # kombinace '+' a '*'
Znova a znova a znova a znova

Řetězce znaků můžeme také přiřazovat do proměnných:

>>> s1 = 'Znova '
>>> s2 = 'a znova '
>>> print s1 + (s2 * 3)
Znova a znova a znova a znova

Všimněte si, že poslední dva příklady dávají stejný výstup.

S řetězci se dá dělat spousta dalších věcí, ale k tomu se podrobněji dostaneme až v dalších tématech. Nejdříve si musíme osvojit základnější znalosti.

Řetězcové proměnné v jazyce VBScript

V jazyce VBScript jsou proměnné (v angličtině) označovány jako variants, protože mohou obsahovat libovolný typ dat. (Nepřekládal jsem jako varianty, protože by se to pletlo s možnostmi.) VBScript se je podle potřeby pokouší převádět na požadovaný typ. To znamená, že do proměnné můžete přiřadit číslo, ale v okamžiku, kdy proměnnou použijete v místě, kde se očekává řetězec, VBScript provede potřebný převod. Dá se říci, že se to podobá chování pythonovského příkazu print, ale podobné chování je rozšířeno na všechny příkazy jazyka VBScript. Pokud chceme překladači napovědět, že se na nějakou číselnou hodnotu má dívat jako na řetězec, uzavřeme ji do uvozovek:

<script language="VBScript">
retezec = "42"
MsgBox retezec
</script>

Poznámka překladatele: Zatímco print se snaží převést vše na řetězec, automatické konverze ve VBScript se principiálně snaží převádět cokoliv na cokoliv. Můžeme se na to také podívat také jinak. Snaha o převod do použitelné podoby je v Pythonu vlastností příkazu print, zatímco ve VBScript je vlastností proměnných samotných. Tuto vlastnost jazyka VBScript ocení především začátečníci a dá se dobře využít u jednoduchých skriptů. U složitějších a rozsáhlejších programů může být podobné chování zdrojem obtížně odhalitelných chyb.

Řetězce můžeme spojovat dohromady. Této operaci se říká zřetězení (konkatenace) a v jazyce VBScript k ní používáme operátor & takto:

<script language="VBScript">
retezec = "Ahoj, " & "vy tam!"
MsgBox retezec
</script>

Řetězce v JavaScript

V jazyce JavaScript mohou být řetězce uzavřeny buď v apostrofech nebo v uvozovkách. Před použitím proměnné ji musíme deklarovat. Používáme k tomu klíčové slovo var. Takže deklaraci a definici dvou řetězcových proměnných provedeme v jazyce JavaScript takto:

<script language="JavaScript">
var retezec1, retezec2;
retezec1 = "Ahoj, ";
retezec2 = "vy tam!";
document.write(retezec1 + retezec2)
</script>

Jako poznámku na závěr uveďme, že v jazyce JavaScript můžeme vytvářet řetězce i jako objekty typu String. O objektech se budeme bavit o něco později. Prozatím můžeme o objektech typu String uvažovat jako o obyčejných řetězcích s určitými vlastnostmi navíc. Hlavní rozdíl spočívá v tom, že je vytváříme trochu jinak:

<script language="JavaScript">
var retezec1, retezec2;
retezec1 = String("Ahoj, ");
retezec2 = String("vy tam!");
document.write(retezec1 + retezec2)
</script>

Níže uvedený text pochází z prvního vydání. Nad tímto textem se nachází aktuální stav po revizi směřující k druhému vydání.

Celá čísla

Celá čísla — v různých programovacích jazycích známá jako integer, nemají desetinnou část — jejich hodnoty se pohybují od velkých záporných hodnot až po velké kladné hodnoty. Tuto důležitou skutečnost bychom si měli zapamatovat. Obvykle neuvažujeme o tom, že by čísla měla být co do velikosti nějak omezena, ale u počítačů existují jejich horní a dolní hranice. Hodnota horní hranice je známa jako MAXINT a závisí na počtu bitů, které váš počítač používá pro reprezentaci čísla. Na většině současných počítačů je to 32 bitů, takže konstanta MAXINT odpovídá hodnotě kolem 2 miliard.

Čísla, která mohou nabývat jak kladných, tak záporných hodnot jsou označována jako celá čísla se znaménkem (signed integer). Někdy se využívají i čísla, která jsou omezena pouze na kladné hodnoty a nulu. Označujeme je jako celá čísla bez znaménka (unsigned integer). (Poznámka překladatele: Pokud na chvíli zapomeneme na omezení horní hranicí, pak v matematice takovým číslům říkáme přirozená čísla.) V takovém případě se horní hranice zvětší na dvojnásobek hodnoty MAXINT — u 32bitových čísel na hodnotu kolem 4 miliard —, protože prostor, který byl jinak vyhrazen pro reprezentaci záporných čísel, může být využit pro reprezentaci dalších kladných čísel.

Protože jsou celá čísla (budeme říkat také čísla typu integer) shora omezena konstantou MAXINT, může nastat situace, kdy součet dvou čísel přesáhne konstantu MAXINT a výsledný součet bude chybný, protože správný výsledek nelze do vyhrazeného prostoru 32 bitů uložit. V některých systémech/jazycích se vrací tato špatná hodnota přímo tak jak vyšla (obvykle je současně nastaven skrytý příznak chyby, který můžete testovat, pokud předpokládáte, že k chybě mohlo dojít). Obvykle se v této situaci nastavuje chybová podmínka, kterou můžete vaším programem ošetřit. Pokud tak neučiníte, program se ukončí. Posledně zmíněným způsobem se chová Python, zatímco Tcl používá přístup zmíněný dříve. BASIC reaguje signalizací chyby, ale neposkytuje žádný způsob, jak ji ošetřit (alespoň já o žádném způsobu nevím).

Aritmetické operátory

S většinou aritmetických operátorů, které budeme potřebovat, jsme se již setkali v kapitole Jednoduché posloupnosti. Zopakujme si je:

Aritmetické a bitové operátory
Příklad Popis významu
M + N Sčítání M a N
M - N Odčítání N od M
M * N Násobení M a N
M / N Dělení, jak čísel typu integer tak reálných čísel. Výsledek záleží na typu čísel M a N. Když je alespoň jedno z čísel M a N reálné, výsledek bude též reálný.
M % N Modulo: nalezne zbytek po celočíselném dělení M : N
M**N Umocňování: M na N-tou

O posledním z nich jsme se ještě nezmínili. Podívejme se na příklad v němž vytvoříme několik proměnných typu integer a poté použijeme operátor pro umocňování:

>>> i1 = 2    # vytvoř proměnnou i1 přiřadím jí hodnotu celého čísla
>>> i2 = 4
>>> i3 = 2**4 # přiřaď výsledek dvě na čtvrtou do i3
>>> print i3
16

Celá čísla v jazyce BASIC

Basic má pro práci s čísly typu integer určitá specifická pravidla. K deklarování proměnné typu integer v jazyce BASIC můžeme použít buď prostého, nepřikrášleného jména, nebo můžeme dát překladači najevo, že je to právě celočíselná hodnota, kterou budeme chtít uchovávat (což vede k mírně efektivnějšímu kódu). Docílíme toho připojením '%' (znak procenta) na konec jména proměnné:

FOO = 8  REM FOO může uchovávat jakýkoliv typ čísla
BAR% = 9 REM BAR může uchovávat pouze čísla typu integer

Zmíníme se ještě o posledním zádrhelu s proměnnými typu integer v jazyce BASIC:

i% = 7
PRINT 2 * i%
i% = 4.5 
PRINT 2 * i%

Povšimněte si, že to vypadá, jako by se přiřazení hodnoty 4.5 do proměnné i% povedlo, ale ve skutečnosti byla přiřazena pouze celočíselná část. Tady si připomeňme, jak se choval Python při dělení čísel typu integer.

Čísla v Tcl

Jak už jsme se dříve zmínili, Tcl všechno ukládá vnitřně jako řetězce. Nicméně, pro koncového uživatele to nepřináší žádné rozdíly, protože Tcl skrytě převádí takové hodnoty na čísla a zpět na řetězce, jako by to skutečně čísla byla. Takže se stále uplatňují omezení na velikost čísel.

Práce s čísly v Tcl je ve srovnání s většinou ostatních jazyků o něco složitější, protože musíte překladači vždy přímo říci, že má provést výpočet zapsaného výrazu. Musíte použít příkaz expr:

% put [expr 6 + 5]
11

Tcl rozpozná hranaté závorky a vyhodnotí tuto část jako první — jako kdybyste ji napsali na příkazový řádek. V našem případě zde nalezne příkaz expr a provede vyhodnocení výrazu. Výsledek je zobrazen na obrazovku příkazem put. Pokud byste do příkazu put uvedli výraz se součtem přímo, Tcl by prostě vytisknul "6 + 5":

% put 6 + 5
6 + 5

Reálná čísla

Jde o čísla s desetinnou částí, o zlomky[4]. Mohou reprezentovat čísla velmi velká, mnohem větší než MAXINT, ale s menší přesností. To znamená, že dvě čísla, která by měla být shodná, ve skutečnosti pro počítač stejná nejsou. Je to dáno tím, že počítač ukládá jen přibližnou hodnotu v závislosti na tom, jakou úroveň detailů čísla je schopen zachytit. Například číslo 4.0 by mohlo být uloženo jako 3.9999999… nebo 4.000000…01. Ve většině případů taková přibližnost postačuje, ale občas může mít důležité dopady. Pokud při používání reálných čísel dostanete nějaké legrační výsledky, mějte tuto skutečnost na paměti.

S desetinnými čísly můžeme provádět stejné operace jako s čísly typu integer. Navíc máme k dispozici operace pro převod na celá čísla odseknutím nebo zaokrouhlením desetinné části.

Komplexní čísla

I když máte základy matematiky, můžete se nad dostupností komplexních čísel v programovacím jazyku podivovat. Pokud tyto základy nemáte, možná jste o komplexních číslech vůbec neslyšeli. Nicméně, některé programovací jazyky, včetně jazyku Python, mají podporu pro typ komplexních čísel zabudovánu přímo do jazyka, zatímco k jiným jazykům se dodávají knihovny nebo funkce, které práci s komplexními čísly umožňují. A ještě než se zeptáte — totéž platí pro matice.

V jazyce Python jsou komplexní čísla reprezentována jako:

(real+imaginaryj)

kde real představuje reálnou složku a imaginary složku imaginární.

Takže sčítání komplexních čísel zapisujeme následovně:

>>> M = (2+4j) 
>>> N = (7+6j)
>>> print M + N 
(9+10j)

Všechny operace určené pro čísla typu integer je možno použít i pro komplexní čísla.

Hodnoty typu Boolean — True a False

Jak už nadpis napovídá, tento typ má pouze dvě hodnoty — True (pravda) a False (nepravda). Některé jazyky podporují boolovské hodnoty přímo, jiné používají konvence, kdy vybraná číselná hodnota (často nula) reprezentuje False a jiná hodnota (často 1 nebo -1) reprezentuje True.

Boolovské hodnoty jsou známy také jako pravdivostní hodnoty, protože vyjadřují skutečnost, zda je něco pravdivé nebo nepravdivé. Dejme tomu, že píšete program, který má zálohovat všechny soubory v adresáři. Můžeme v cyklu postupovat tak, že uložíme soubor jednoho jména a potom se operačního systému zeptáme, jak se jmenuje další soubor. Pokud už žádný další soubor neexistuje (tj. byly zpracovány všechny soubory v adresáři), vrátí se prázdný řetězec. Vrácené jméno souboru tedy můžete porovnat s hodnotou prázdného řetězce a výsledek můžete uložit jako boolovskou hodnotu (pokud je vrácený řetězec prázdný, uloží se True). Později si ukážeme, jak můžeme takto uložený výsledek použít.

Boolovské (nebo také logické) operátory
Zápis Jméno operace Popis významu
A and B současně True, když A i B jsou True. V jiném případě je výsledkem False.
A or B NEBO True když oba nebo jeden z A, B jsou True. False, když oba A i B jsou False.
A == B ROVNOST True když A je rovno B.
A != B
nebo
A <> B
NEROVNOST True když A není rovno B.
not B NEGACE True když B není True.

Poznámka: poslední operace se týká jedné hodnoty, zatímco ostatní porovnávají dvě hodnoty.

Kolekce

Pro studium kolekcí a jejich chování byla v počítačové vědě vybudována celá disciplína. Někdy bývají kolekce označovány pojmem kontejnery. V této sekci se nejdříve podíváme na kolekce, které podporuje jazyk Python. Nakonec stručně shrneme, s jakými dalšími typy kolekcí se můžeme setkat v jiných jazycích.

Kolekce v jazyce Python

Seznam

Seznam (anglicky list [list]) je tvořen posloupností položek. Od pole se liší tím, že může neustále růst — prostě přidáme další položku. Na druhou stranu, k položkám seznamu obvykle nemůžeme přistupovat prostřednicvím indexu, takže při vyhledávání položky podle jejího čísla v pořadí musíme postupovat od začátku seznamu směrem k jeho konci a kontrolovat, zda už jsme na položce, kterou chceme.

V jazycích Python a Tcl jsou seznamy již zabudovány (jsou jeho součástí). V jazyce BASIC je to o něco obtížnější, protože musíme použít určité programátorské triky k tomu, abychom chování seznamů nasimulovali. Programátoři v jazyce BASIC to obvykle obcházejí tím, že místo seznamu prostě použijí velmi velké pole. V jazyce Python můžeme položky seznamu zpřístupňovat i prostřednicvím indexu — narozdíl od toho, co bylo řečeno v předcházejícím odstavci. Jak uvidíme dále, tento rys jazyka je velmi užitečný.

Operace nad seznamem

Python definuje nad kolekcemi řadu operací. Téměř všechny z nich lze aplikovat na seznamy. Část operací lze aplikovat na další typy kolekcí a také na řetězce, které jsou vlastně jen speciálním případem seznamu znaků. V jazyce Python seznam vytvoříme a zpřístupníme s použitím hranatých závorek. Pokud použijeme pouze hranaté závorky a nic do nich nevepíšeme, vytvoříme prázdný seznam. Seznam s hodnotami vytvoříme tak, že požadované hodnoty zapíšeme dovnitř závorek a oddělíme je čárkami:

>>> seznam = []
>>> jinySeznam = [1, 2, 3]
>>> print jinySeznam
[1, 2, 3]

K jednotlivým položkám můžeme přistupovat pomocí indexu, který uvedeme v hranatých závorkách. První položka seznamu má přidělen index 0 (nula):

>>> print jinySeznam[2]
3

Hodnoty položek seznamu můžeme podobným způsobem i měnit:

>>> jinySeznam[2] = 7
>>> print jinySeznam
[1, 2, 7]

Záporné hodnoty indexového čísla používáme pro zpřístupnění položek indexovaných vůči konci seznamu. Nejčastěji se používá index -1 (mínus jedna), který zajistí zpřístupnění poslední položky seznamu:

>>> print jinySeznam[-1]
7

Můžeme také přidat novou položku na konec seznamu. Použijeme k tomu operátor append():

>>> seznam.append(42)
>>> print seznam
[42]

Položkou seznamu může být dokonce i jiný seznam, takže pokud připojíme na konec prvního seznamu náš druhý seznam, dopadne to takto:

>>> seznam.append(jinySeznam)
>>> print seznam
[42, [1, 2, 7]]

Všimněte si, že výsledkem je seznam složený ze dvou položek, kde druhou položku tvoří opět seznam (jak je znázorněno párem okolních hranatých závorek). Díky tomu můžeme tabulky nebo mřížky vytvářet jako seznamy seznamů. V našem příkladu můžeme prvek s hodnotou 7 zpřístupnit pomocí dvojitého indexu:

>>> print seznam[1][2]
7

Hodnota prvního indexu (tj. 1) zpřístupní druhou položku seznamu, která je vlastně seznamem. Hodnota druhého indexu (tj. 2) zpřístupní třetí položku zmíněného podseznamu.

Opačnou operací k přidávání položky je, samozřejmě, operace rušení položky, kterou zajistíme provedením příkazu del:

>>> del seznam[1]
>>> print seznam
[42]

Pokud chceme spojit dva seznamy do jednoho, můžeme použít stejný operátor pro zřetězení '+', který jsme již použili dříve pro řetězce:

>>> print seznam
[42]
>>> print jinySeznam
[1, 2, 7]
>>> novySeznam = seznam + jinySeznam
>>> print novySeznam
[42, 1, 2, 7]

Podobně můžeme pomocí opakovacího operátoru vytvořit seznam naplněný několika položkami se stejnou hodnotou:

>>> seznamNul = [0] * 5
>>> print seznamNul
[0, 0, 0, 0, 0]

A nakonec, délku seznamu (počet jeho položek) můžeme zjistit, když použijeme zabudovanou funkci len():

>>> print len(seznam)
1
>>> print len(seznamNul)
5

Seznamy v Tcl

Rovněž jazyk Tcl má vestavěný typ seznam a definuje sadu příkazů, které se seznamy pracují. Tyto příkazy začínají písmenem 'l' (malé písmeno el, protože anglický pojem pro seznam zní list). Jde například o příkazy linsert, lappend, lindex, a další. Následuje příklad vytvoření jednoduchého seznamu v Tcl a zpřístupnění jeho položky:

% set L [list 1 2 3]
% put [lindex $L 2]
3

N-tice

Typ n-tice (anglicky tuple) není řadou jazyků vůbec podporován. Ale v těch jazycích, kde jsou n-tice podporovány, se ukazuje, že je to velmi užitečný rys. N-tice je ve skutečnosti jen libovolná kolekce hodnot, se kterou můžeme zacházet jako s jedním celkem. V mnoha ohledech se n-tice podobá seznamu, ale jeden významný rozdíl spočívá v tom, že n-tice jsou neměnné (anglicky immutable). To znamená, že jakmile je jednou n-tice vytvořena, nelze ji měnit (tj. nelze měnit, přidávat nebo rušit jednotlivé položky n-tice). V jazyce Python se n-tice zapisují jako posloupnost hodnot oddělených čárkami, která je uzavřená v kulatých závorkách — takto:

>>> ntice = (1, 3, 5)
>>> print ntice[1] # zpřístupníme položku indexem, jako u seznamu
3
>>> ntice[2] = 7   # chyba: položku n-tice nelze měnit
Traceback (most recent call last):
  File "", line 1, in ?
    ntice[2] = 7
TypeError: object doesn't support item assignment
           objekt nepodporuje přiřazování hodnot do položek

Zapamatujme si hlavně to, že kulaté závorky používáme při vytváření n-tice, že hranaté závorky se používají pro uvedení indexu při přístupu k jejím položkám a že jednou vytvořenou n-tici nelze později měnit. Ostatní operace se podobají operacím nad seznamy.

Slovník (vyhledávací tabulka)

Slovník (anglicky dictionary [dykšnri]) jak už název napovídá, obsahuje hodnoty spojené s klíčem; stejně jako například výkladový slovník uvádí pro dané slovo popis jeho významu. Hodnotu zpřístupňujeme vyhledáváním podle klíče — používáme klíč místo indexu. Narozdíl od výkladového slovníku, klíč obecně nemusí být znakovým řetězcem (ačkoliv se zrovna řetězec často používá). Může to být hodnota libovolného neměnného typu (immutable), včetně čísel a n-tic. Hodnota, která je s klíčem svázaná, může být libovolného datového typu jazyka Python. Slovníky jsou obvykle implementovány s využitím programovací techniky známé jako hash table[5] [heš tejbl]. Z tohoto důvodu se pro datový typ slovník občas používá zkrácený pojem hash. V české terminologii se spíše využívá druhá část úplného pojmu, tedy tabulka. Nemá to tedy nic společného s drogami.

K hodnotám ve slovníku můžeme přistupovat pouze prostřednictvím klíče, takže do slovníku můžeme vložit pouze prvky s jednoznačným klíčem (pro jeden klíč nelze současně uchovávat dvě hodnoty). Slovníky jsou velmi užitečnými strukturami. Python je poskytuje jako zabudovaný typ, ačkoliv v mnoha dalších jazycích musíte použít odpovídající modul nebo si dokonce musíte typ slovník naprogramovat sami. Slovníky můžeme používat mnoha způsoby a později si ještě ukážeme řadu příkladů. V tomto okamžiku si ale ukažme alespoň jak v jazyce Python slovník vytvoříme, jak do něj vložíme některé položky a jak je opět zpřístupníme (přečteme):

>>> dict = {}
>>> dict['boolean'] = "Hodnota, která je buď True nebo False"
>>> dict['integer'] = "Celé číslo"
>>> print dict['boolean']
Hodnota, která je buď True nebo False

Všimněte si, že počáteční hodnotu slovníku nastavíme pomocí složených závorek (zde prázdný slovník). Poté používáme hranaté závorky pro přiřazování a čtení hodnot.

Řada operací nad kolekcemi, se kterými jsme se do této chvíle seznámili, není u slovníků — vzhledem k jejich vnitřní struktuře — podporována. Nefunguje zde ani operátor zřetězení, operátor opakování, ani operace append(). Abychom si mohli zpřístupnit hodnoty klíčů, máme k dispozici funkci keys(). Ta vrací seznam všech klíčů, které seznam používá.

Pokud už toho začínáte mít plné zuby, můžete v tomto místě přejít k další kapitole. Jakmile se začnete setkávat s datovými typy o kterých jsme se ještě nezmínili, nezapomeňte se vrátit zpět k této kapitole a dočíst si ji.

Další typy kolekcí

Pole nebo vektor

Jde o seznam položek, které jsou snadno a rychle přístupné prostřednictvím indexu. Obvykle musíme předem říci, kolik položek budeme chtít ukládat. Pokud máme například pole A, pak můžeme získat hodnotu jeho třetí položky tím, že napíšeme A[3]. Pole patří k podstatným základům jazyka BASIC. Ve skutečnosti jsou vlastně jediným vestavěným typem s vlastnostmi kolekce. V jazyce Python jsou pole simulována s využitím seznamů a v Tcl jsou pole implementována s využitím slovníků.

Následuje ukázka pole v jazyce BASIC:

DIM MojePole(20) REM Vytvoř pole s 20 položkami

MojePole(1) = 27
MojePole(2) = 50
FOR i =1 TO 5
   PRINT MojePole(i)
NEXT i

Všimněte si, že v jazyce BASIC se pole začínají indexovat hodnotou 1. Je to nezvyklé — ve většině programovacích jazyků je počáteční hodnotou indexu hodnota 0 (nula). Pro pole zde nejsou definovány žádné další operátory. Vše co s polem můžeme dělat je jeho vytvoření, přiřazení hodnot a čtení hodnot.

Zásobník

O zásobníku (anglicky stack [stek]) můžeme uvažovat jako o na sobě naskládaných podnosech v samoobslužné restauraci. Zaměstnanec restaurace přidává čisté podnosy na vrchol sloupce podnosů a zákazníci je jeden po druhém z vrcholu zase odebírají. Podnosy ve spodní části zásobníku se používají jako poslední (a také nejméně). Datový zásobník se chová stejně: každou položku buď do zásobníku vložíme (operace se označuje push [puš]) nebo ji ze zásobníku vybereme (pop). Vybírá se vždy ta položka, která byla do zásobníku vložena jako poslední. Tato vlastnost zásobníku je někdy označována jako Last In First Out (poslední dovnitř, první ven) nebo LIFO. Jednou z užitečných vlastností zásobníku je to, že jej můžeme využít k obrácení pořadí položek seznamu tím, že jednotlivé položky seznamu postupně vložíme do zásobníku a poté je postupně vybíráme z vrcholu zásobníku a vkládáme do seznamu. Výsledkem bude počáteční seznam s obráceným pořadím položek.

Typ zásobník není vestavěným typem jazyků Python, Tcl ani BASIC. Jeho chování musíme vyjádřit v kódu programu. Nejvhodnější bývá obvykle vyjít z typu seznam, protože — jako v případě zásobníku — počet položek seznamu může narůstat podle potřeby.

Poznámka překladatele k zásobníku: Pokud použijeme seznam v roli zásobníku, pak jeho metoda append() realizuje stejnou funkčnost jako operace push(). Kromě toho Python pro seznam (ale i pro další struktury) definuje metodu pop() s typickým významem. Pokud nám vadí, že nemáme k dispozici přímo metodu push(), ale stačí nám zavedení nějakého zásobníku a vlastních funkcí push() a pop(), které pracují právě a jen s tímto zásobníkem, není to ani tak složité — viz následující ukázka:

>>> zasobnik = []
>>> push = zasobnik.append
>>> pop = zasobnik.pop
>>> push
<built-in method append of list object at 0x009C5B70>
>>> pop
<built-in method pop of list object at 0x009C5B70>
>>> push(1)
>>> push(2)
>>> push(3)
>>> zasobnik
[1, 2, 3]
>>> print pop()
3
>>> zasobnik
[1, 2]
>>> pop()
2
>>> pop()
1
>>> zasobnik
[]
>>> pop()

Traceback (most recent call last):
  File "<pyshell#13>", line 1, in -toplevel-
    pop()
IndexError: pop from empty list
>>>

Na prvním řádku vytvoříme prázdný seznam a na dalších dvou řádcích navážeme jména push a pop na příslušný kód objektu zasobnik (viz výpis na dalších řádcích). Pokud potom napíšeme push(1), provede se naprosto stejná činnost, jako kdybychom provedli zasobnik.append(1). Povšimněte si také, že pokus o pop() nad prázdným zásobníkem nelze tolerovat — je vyvolána výjimka.

Jakmile se naučíte pracovat s třídami a objekty, zjistíte, že není obtížné vytvořit pro zásobník vlastní třídu, která bude zveřejňovat jen požadované operace push() a pop(), případně další, dle vaší volby. Pokud se vám nastíněné, čistě objektové řešení zdá při vašich momentálních schopnostech a dovednostech nedostižné, nic si z toho nedělejte. Je to naprosto normální.

Multimnožina

Multimnožina (anglicky bag) představuje kolekci položek, u kterých není definováno pořadí a která může obsahovat více položek se stejnou hodnotou. Tento datový typ obvykle poskytuje operace pro přidávání, vyhledávání a odstraňování položek. V jazycích Python a Tcl se pro tento účel používají seznamy. V jazyce BASIC musíme multimnožinu vytvořit pomocí velkého pole.

Množina

Množina (anglicky set) může uchovávat pouze jeden výskyt každé položky. Obvykle můžeme testovat, zda daná položka je či není prvkem množiny. Položky můžeme do množiny přidávat a odstraňovat. Dvě množiny můžeme spojovat dohromady různými způsoby, které známe z matematické teorie množin (jako je například sjednocení, průnik, atd.). Žádný ze zmiňovaných jazyků nemá k dispozici datový typ množiny přímo, ale v jazycích Python a Tcl můžeme množinu snadno vytvořit pomocí typu slovník.

Fronta

Fronta (anglicky queue [kjú]) se podobá zásobníku ale s tím rozdílem, že první položka, která se dostane dovnitř, je zároveň první položkou, která se dostane ven. Tomuto chování se říká First In First Out (první dovnitř, první ven) nebo FIFO.

Existuje celá řada dalších datových typů s vlastnostmi kolekce, ale ty, o kterých jsme se zmínili, patří mezi hlavní, se kterými se můžete setkat. (V našem kurzu programování se ve skutečnosti budeme zabývat jen některými z výše zmíněných.)

Poznámka překladatele k frontě: Podobně, jako v případě zásobníku, můžeme i frontu jednoduše implementovat s využitím operací nad seznamem. Pro operaci zařazení do fronty opět použijeme metodu append() (této operaci se někdy říká queueUp() nebo pushBack()). Pro operaci výběru ze začátku fronty můžeme použít pop(0). Parametr říká, z kterého místa prvek odstraňujeme. V případě zásobníku jsme parametr nezadávali, takže se použila jeho implicitní hodnota -1 s významem index posledního prvku.

Soubory

Jako uživatelé počítače o souborech zajisté víte vše — tvoří základ pro téměř vše, co s počítači děláme. Zjištění, že většina programovacích jazyků poskytuje speciální datový typ file (soubor), by vás tedy nemělo překvapit. Soubory a jejich zpracování jsou natolik důležité, že se jimi budeme zabývat až o něco později, v samostatné kapitole.

Datum a čas

Pro datum a čas bývá často vyhrazen samostatný datový typ. Někdy se pro jejich reprezentaci jednoduše používá velké číslo (typicky se jím vyjadřuje počet sekund, které uplynuly od zvoleného pevného data a času). Jindy se pro jejich uložení používá datový typ, který označujeme jako složený a který bude popsán v následujícím textu. Takový datový typ obvykle umožňuje snadnější zjištění měsíce, dne, hodiny atd.

Složený, uživatelem definovaný typ

Někdy se ukáže, že výše popsané základní jednoduché typy nevyhovují a to ani po jejich uspořádání s využitím kolekcí. Někdy prostě chceme sdružit skupinu datových bitů dohromady a pracovat s nimi jako s jednou položkou. Příkladem může být položka adresy: číslo domu, ulice, město a směrovací číslo.

Většina programovacích jazyků dovoluje podobné informace sdružit to takzvaného záznamu (anglicky record [rikód]) nebo struktury (structure [strakčr]).

V jazyce BASIC vypadá definice takového záznamu následovně:

Type Adresa
    CisloDomu AS INTEGER
    Ulice AS STRING * 20
    Mesto AS STRING * 15
    PSC AS STRING * 7 
End Type

Číslo za slovem STRING vyjadřuje maximální možnou délku řetězce.

V jazyce Python stejný případ vyjádříme trochu jinak:

>>> class Adresa:
...     def __init__(self, Dum, Ul, Mesto, PSC):
...         self.CisloDomu = Dum
...         self.Ulice = Ul
...         self.Mesto = Mesto
...         self.PSC = PSC
...

Tento zápis se vám může zdát poněkud záhadný, ale nemějte obavy. V kapitole o objektově orientovaném programování si vysvětlíme, co znamená def __init__(...) a self. Povšimněme si jen toho, že identifikátor __init__ obsahuje na obou stranách dvojici znaků podtržení. Jde o pythonovskou konvenci, o které se zmíníme později. Když někteří lidé zkoušeli zapsat uvedený příklad na vyzývacím řádku interpretu jazyka Python, měli s tím určité poblémy. Na konci této kapitoly naleznete zvýrazněný úsek textu, který části příkladu podrobněji vysvětluje. Ale pokud vám to víc vyhovuje, můžete s jeho studiem počkat až na pozdější dobu, až se v průběhu kurzu dozvíte všechny podrobnosti. Pokud se pokoušíte o zapsání příkladu na vyzývací řádek (anglicky prompt) jazyka Python, ujistěte se, že jste použili stejný způsob odsazení. Jak uvidíme později, Python je v otázce odsazování úrovní velmi puntičkářský.

Hlavní poznatek, který byste si měli z tohoto příkladu odnést, by měl být ten, že lze sloučit několik kousků dat do jediné struktury.

Přístup ke složeným datovým typům

Hodnotu složeného datového typu můžeme také přiřadit do proměnné. Ale abychom mohli přistupovat k jednotlivým složkám hodnoty složeného typu, musíme použít speciální zápis, který je určen konkrétním programovacím jazykem. Obvykle se k zápisu používá tečka.

Pokud budeme uvažovat výše uvedený příklad s adresou, pak bychom v jazyce BASIC mohli napsat:

DIM Adr AS Adresa
Adr.CisloDomu = 7
Adr.Ulice = "Havlickova"
Adr.Mesto = "Stare Mesto"
Adr.PSC = "790 58"
PRINT Adr.CisloDomu," ",Adr.Ulice

V jazyce Python — za předpokladu, že jste již napsali výše uvedenou definici třídy Adresa — můžeme psát:

Adr = Adresa(7, "Havlickova", "Stare Mesto", "790 58")
print Adr.CisloDomu, Adr.Ulice

Tím se vytvoří instance našeho typu Adresa a přiřadí se do proměnné Adr. Poté s využitím tečkového operátoru tiskneme složky CisloDomu a Ulice. Můžete, samozřejmě, vytvořit více proměnných typu Adresa a do každé z nich přiřadit jiné číslo domu, ulici, a tak dále.

Jak na to v jazyce Tcl

Vyjádření složeného typu se v jazyce Tcl nejvíce blíží uložení jednotlivých složek do seznamu. Ale abychom se znovu dostali k hodnotám složek, musíme si pamatovat jejich pořadí. Abychom si to trochu usnadnili, můžeme si čísla položek uložit do pomocných proměnných. V takovém případě by uvedený příklad mohl vypadat následovně:

set CisloDomu 0
set Ulice 1
set Mesto 2
set PSC 3
set adr [list 7 "Havlickova" "Stare Mesto" "790 58"]
puts [format "%s %s" [lindex $adr $CisloDomu] [lindex $adr $Ulice]]

Všimněte si, jak se v Tcl používá formátovací řetězec a jak jsou konstrukce s hrananými závorkami zanořené do sebe.

Operace definované uživatelem

V některých programovacích jazycích mohou mít uživatelské datové typy uživatelem definovány i operace. Tento rys patří k základům takzvaného objektově orientovaného programování. Tomuto tématu bude věnována samostatná kapitola, ale v tomto okamžiku si uveďme alespoň to, že objekt se v podstatě tvořen datovými složkami a operacemi definovanými nad těmito datovými složkami. Vše je zabaleno dohromady a vystupuje to jako jediný celek. Python objekty široce využívá ve své standardní knihovně modulů a současně nám jako programátorům umožňuje vytváření svých vlastních typů objektů.

Operace objektu se zpřístupňují stejným způsobem, jako datové členy uživatelsky definovaného typu — prostřednictvím tečkového operátoru —, ale jinak vypadají jako funkce. Těmto zvláštním funkcím se říká metody. Už jsme se s tím setkali u seznamu v podobě operace append(). Vzpomeňte si, že abychom ji mohli použít, museli jsme volanou funkci spojit se jménem proměnné:

>>> seznam = []       # prázdný seznam
>>> seznam.append(42) # volání metody objektu seznam
>>> print seznam
[42]

Pokud je typ objektu — říká se mu třída — definován uvnitř nějakého modulu, musíme tento modul importovat (jako jsme si již dříve ukázali v případě modulu sys). Jménu objektového typu předřadíme jméno modulu a vytvoříme instanci třídy (tj. objekt), který bude uložen v proměnné. Tu již můžeme používat aniž bychom uváděli jméno modulu.

Ukážeme si to na fiktivním modulu meat, který definuje třídu Spam[6]. Importujeme uvedený modul, vytvoříme instanci třídy Spam a použijeme její operace a datové položky:

>>> import meat
>>> mySpam = meat.Spam()     # vytvoření instance, užití modulového jména
>>> mySpam.slice()           # užití operace objektu třídy Spam (ukrojit)
>>> print mySpam.ingredients # přístup k datům objektu
{'Pork': '40%', 'Ham': '45%', 'Fat': '15%'}

Pokud pomineme nutnost vytvoření instance objektu, pak neexistuje podstatný rozdíl mezi používáním objektů, které moduly poskytují, a funkcí, které se v modulech nacházejí. O jménu objektu můžeme uvažovat jako o visačce, která drží odpovídající funkce a proměnné seskupené dohromady.

Jiný způsob v pohledu na věc je takový, že objekty reprezentují skutečné věci v našem světě, se kterými můžeme — jako programátoři — něco dělat. Právě toto je pohled, který původně vedl ke zrození myšlenky používání objektů v programech. Týkal se zápisu počítačové simulace situací v reálném světě.

Nástroje pro přidávání operací do složených datových typů neposkytuje ani QBASIC, ani Tcl. Ale pro Tcl existují přídavné knihovny, které to umožňují. Umožňuje to i modernější dialekt jazyka BASIC — Visual Basic.

Specifické operátory jazyka Python

Mým prvotním cílem, kterému jsem zasvětil tento výukový kurs, je naučit vás programovat. A ačkoliv zde používám jazyk Python, nevidím žádný důvod, proč byste si po přečtení tohoto textu nemohli nastudovat něco o jiném jazyce a zaměřit se na něj. Dokonce očekávám, že právě toto uděláte, protože neexistuje jediný programovací jazyk — Python není výjimkou — který se hodí na všechno. Na druhou stranu, protože jsem si vytknul takový cíl, nevěnuji se výuce všech rysů jazyka Python, ale zaměřuji se na ty, které můžete obvykle nalézt i u jiných jazyků. Výsledkem tohoto rozhodnutí je skutečnost, že některé specifické rysy jazyka Python — i když jsou poměrně mocné — nepopisuji vůbec. Patří mezi ně i speciální operátory. U většiny programovacích jazyků můžeme nalézt některé operace, které jiné jazyky nepodporují. Často jsou to právě tyto unikátní operátory, které dávají novým programovacím jazykům vzniknout a které jsou určitě důležitým faktorem určujícím jak populárním se jazyk stane.

Python například podporuje takové netradiční operace, jako jsou získání výřezu ze seznamu (anglicky list slicing [list slajsing]) (spam[X:Y]) a přiřazení n-tice (X, Y = 12, 34). (Posledně uvedenému příkazu se říká také násobný nebo paralelní přiřazovací příkaz.) Python poskytuje i prostředek k provedení požadované operace nad každým členem kolekce — slouží k tomu funkce map(). Takových věcí je mnohem více. Často se říká, že "Python dostáváte i s přiloženými bateriemi". Pokud se budete chtít dozvědět, jak tyto specifické operace jazyka Python fungují, budete muset nahlédnout do jeho dokumentace.

Nakonec bych chtěl upozornit na to, že ačkoliv říkám, že tyto operace jsou specifické pro jazyk Python, neříkám, že je nemůžete nalézt v žádném jiném jazyce. Spíše chci říci, že je v každém jazyce nenaleznete všechny. Operace, kterými se zabýváme v hlavním textu, jsou v nějaké podobě obecně dostupné ve všech moderních programovacích jazycích.

Tím uzavíráme náš pohled na programátorské suroviny. Nyní se posuňme k více vzrušujícímu tématu postupů (programovacích technik) a uvidíme, jak můžeme zmíněné suroviny využít.

Podrobněji vysvětlený příklad Adresa

Ačkoliv, jak už jsem řekl dříve, budou detaily tohoto příkladu vysvětleny později, někteří čtenáři měli problémy se zprovozněním příkladu. Tato poznámka vysvětluje kód, zapsaný v jazyce Python, řádek po řádku. Úplný zápis příkladu vypadá následovně:

>>> class Adresa:
...     def __init__(self, Dum, Ul, Mesto, PSC):
...         self.CisloDomu = Dum
...         self.Ulice = Ul
...         self.Mesto = Mesto
...         self.PSC = PSC
...
>>> Adr = Adresa(7, "Havlickova", "Stare Mesto", "790 58")
>>> print Adr.CisloDomu, Adr.Ulice

Zde je vysvětlení:

>>> class Adresa:

Příkaz class (třída) říká, že hodláme definovat nový typ, který se v tomto případě nazývá Adresa. Dvojtečka vyjadřuje skutečnost, že všechny následující odsazené řádky budou součástí definice třídy. Definice končí prvním neprázdným řádkem, který není vůči prvnímu řádku definice třídy Adresa odsazen. Pokud používáte prostředí IDLE, pak si můžete všimnout, že editor po stisku klávesy Enter další řádek automaticky odsadil. Pokud jste Python spustili z příkazového řádku okna MS-DOS, pak na vyzývacím řádku překladače jazyka Python musíte provést požadované odsazení ručně, vložením mezer. Překladači jazyka Python nezáleží na tom, o kolik pozic odsadíte, pokud budete odsazovat pořád o stejnou hodnotu.

...     def __init__(self, Dum, Ul, Mesto, PSC):

První položkou uvnitř definice naší třídy je to, čemu říkáme definice metody. Důležitým detailem je to, že jméno metody začíná a končí dvojicí znaků podtržení. Jde o konvenci pro zápis jmen, kterým Python přisuzuje zvláštní význam. Tato konkrétní metoda se nazývá __init__ a jde o speciální operaci, kterou Python automaticky provede hned po vytvoření instance naší nové třídy — jak uvidíme za chvíli. Dvojtečka, tak jako v předchozím případě, jednoduše překladači jazyka Python říká, že následující skupina odsazených řádků tvoří definici této metody.

...         self.CisloDomu = Dum

Tento řádek a tři následující řádky přiřazují hodnoty vnitřním (datovým) položkám našeho objektu. Jsou odsazeny vůči řádku s příkazem def, abychom překladači jazyka Python naznačili, že představují skutečnou definici těla operace __init__. Prázdný řádek říká interpretu jazyka Python, že definice třídy byla ukončena, takže Python znovu zobrazí vyzývací řádek ve tvaru '>>> '.

>>> Adr = Adresa(7, "Havlickova", "Stare Mesto", "790 58")

Tento řádek zajistí vytvoření nové instance (tj. nového objektu) typu Adresa a Python automaticky použije výše definovanou operaci __init__ k přiřazení zadaných hodnot do vnitřních položek objektu. Vytvořená instance je přiřazena do proměnné Adr stejným způsobem, jako by byla přiřazena hodnota jiného datového typu.

>>> print Adr.CisloDomu, Adr.Ulice

Nyní tiskneme hodnoty dvou vnitřních položek objektu, které jsme zpřístupnili pomocí tečkového operátoru.

Jak jsem již řekl, dalšími detaily se budeme v tomto kurzu zabývat později. Klíčový poznatek, který byste si z tohoto měli odnést je, že nám Python umožňuje vytvořit náš vlastní datový typ a používat ho stejně dobře jako vestavěné typ.

Zapamatujte si

Pokud vás napadne, co by se dalo na překladu této kapitoly vylepšit, zašlete e-mail odklepnutím . Tím bude do subjektu dopisu automaticky vložena informace o jméně a verzi tohoto HTML dokumentu.

$Id: cztutdata.html,v 1.5 2004/08/03 07:02:47 prikryl Exp $