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. Při programování je to podobné. 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. U čísel jsme si například ukázali, že je můžeme sčítat. Sčítání je tedy 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í.

Pravidla pro tvorbu jmen proměnných jsou závislá na konkrétním programovacím jazyce. Každý jazyk předepisuje, které znaky mohou být součástí jména proměnné, a které ne. V některých jazycích — a patří k nim i Python a JavaScript — záleží na velikosti písmen a v angličtině jsou označovány jako case sensitive [keis sensitiv], čili citlivé na velikost. Jiné jazyky, jako například VBScript, velká a malá písmena nerozlišují. Jazyky citlivé na velikost písmen po programátorovi vyžadují trošku pečlivější přístup. Velmi nám pomůže, když budeme při volbě jmen proměnných používat určitý systém. Jeden z běžných stylů, který budeme často používat, zahajuje jméno proměnné malými písmeny a u každého dalšího slova uvádí první písmeno velké:

velmiDlouheJmenoPromenneSOddelovanimSlovVelkymiPismeny

Poznámka překladatele: Pro jména proměnných musíme v jazyce Python volit písmena bez diakritických znamének.

Nebudeme zde podrobněji probírat pravidla popisující, které znaky můžeme v našich jazycích používat. Při dodržování stylu používaného v ukázkách byste se neměli setkat s nějakými problémy.

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 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 + S2Spojení řetězce S1 a S2
S1 * NN-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 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 type="text/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 type="text/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. Proměnné, které použijeme pro jejich zpřístupnění, musíme před použitím 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 type="text/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 type="text/javascript">
var retezec1, retezec2;
retezec1 = String("Ahoj, ");
retezec2 = String("vy tam!");
document.write(retezec1 + retezec2)
</script>

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. (V jazyce VBScript je to jen kolem 32 tisíc. Pro reprezentaci čísla se používá jen 16 bitů, čili dva bajty, takže můžeme vyjádřit čísla v rozmezí přibližně +/-32 tisíc.)

Čí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 (často 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šak v této situaci vyvolá chybový stav, který můžete vaším programem zjistit a ošetřit. Pokud tak neučiníte, program se ukončí. Jazyky VBScript a JavaScript se chovají posledně zmíněným způsobem. Poslední verze jazyka Python se v chování mírně liší. Od verze 2.3 výše Python automaticky převádí celé číslo na něco, čemu se říká velké celé číslo (long integer; nezaměňujte s typem long v jazycích C a C++, kdy se číslo ukládá na 32 bitech). Jde o specifickou vlastnost jazyka, která umožňuje pracovat s celými čísly o prakticky neomezené velikosti. Nic ovšem není zadarmo. Platíme za to cenou mnohem pomalejšího zpracování. Přinejmenším si však můžeme být jisti tím, že naše výpočty nakonec skončí korektně. Navíc rychlost je v počítačovém světě velmi relativní. Pokud takových velmi velkých celých čísel nezpracováváme mnoho, pravděpodobně si rozdílu ani nevšimnete. To, že se skutečně jedná o velké celé číslo můžeme poznat podle toho, že je Python zobrazuje s připojeným 'L' (jako long):

>>> 1234567 * 3456789
4267637625363L
>>> _

Povšimněte si, že jsme zde nepoužili příkaz print. Pokud bychom tak učinili, zmíněné 'L' by zůstalo skryto. Python umožňuje v interaktivním režimu dva způsoby zobrazování hodnot. Výsledek použití příkazu print je obvykle hezčí (ve smyslu snadnější čitelnosti), ale prosté použití hodnoty, jako ve výše uvedeném příkladu, nám občas odhalí více detailů. Zkuste si příklady z předchozích témat zapsat bez použití příkazu print a zaměřte se na pozorování drobných rozdílů v zobrazení. Příkaz print budu používat také z toho důvodu, že mnohé jazyky jeho použití vyžadují. A také chci, aby vám do krve přešly dobré obecné návyky a ne pouze podlné postupy, které vám umožňuje Python.

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é operátory v jazyce Python
PříkladPopis 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 a přiřaď 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 VBScript

Jak již bylo uvedeno výše, hodnoty typu integer jsou v jazyce VBScript omezeny menší hodnotou MAXINT, která odpovídá uložení na 16 bitech — konkrétně zhruba +/-32 tisíc. Pokud potřebujete pracovat s větší celočíselnou hodnotou, můžete použít long. Ten co do rozsahu odpovídá typu integer, který je standardně používán v jazyce Python. Ve VBScript lze používat i typ byte, který definuje čísla uložená na 8 bitech, s maximální hodnotou 255 (interval 0 až 255). V praktických případech vám většinou bude vyhovovat použití standardního typu integer.

Podporovány jsou všechny aritmetické operátory.

Čísla v jazyce JavaScript

Jistě není žádným překvapením, že JavaScript také definuje numerický typ. Čísla mají opět podobu objektu, viz dále, a nazývají se Number (tj. číslo). Jak originální, že? :-)

V jazyce JavaScript lze použít i takzvané Not a Number neboli NaN (ne-číslo nebo toto-není-číslo). Jde o speciální verzi objektu Number a reprezentuje neplatné číslo. Většinou se používá v roli výsledku nějaké operace, která je z matematického hlediska nepřípustná. Hlavní myšlenka zavedení NaN spočívá v možnosti testovat některé typy chyb aniž by došlo k přerušení programu. JavaScript definuje i další speciální verze typu Number, které reprezentují kladné a záporné nekonečno. V programovacích jazycích se tento rys objevuje zřídka. Číselné objekty v jazyce JavaScript reprezentují buď celá čísla nebo reálná čísla — viz dále.

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 reálnými čísly, známými také jako čísla s plovoucí řádovou čárkou (floating-point numbers), 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.

Python, VBScript i JavaScript práci s reálnými čísly podporují. V jazyce Python je vytvoříme jednoduše tím, že uvedeme zápis čísla, ve kterém se vyskytuje desetinná tečka — jak jsme si ukázali v části Jednoduché posloupnosti. V jazycích VBScript a JavaScript nejsou celá čísla a reálná čísla při používání jasně rozlišována. Jednoduše je používáme a překladač jazyka si s tím většinou dobře poradí.

Komplexní nebo imaginární čísla

Pokud máte základy matematického nebo jiného vědeckého vzdělání, pak vás možná napadlo: A co komplexní čísla? Pokud tyto základy nemáte, možná jste o komplexních číslech vůbec neslyšeli. V takovém případě můžete tuto část přeskočit, protože vám zde uvedená fakta k ničemu nebudou. 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 používané pro čísla typu integer je možno použít i pro komplexní čísla.

VBScript ani JavaScript práci s komplexními čísly nepodporují.

Hodnoty typu Boolean — True a False

Tento podivně vypadající název typu je pojmenován po matematikovi 19. století, George Boolovi, který se zabýval studiem logiky. 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. Bylo tomu tak i u jazyka Python, a to až do verze 2.2 včetně. Od verze 2.3 podporuje Python boolovské hodnoty přímo — používá hodnoty True a False.

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, pokud ne, uložíme False). Později si ukážeme, jak můžeme takto uložený výsledek použít.

Boolovské (nebo také logické) operátory
ZápisJméno operacePopis 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.

Jazyk VBScript, stejně jako Python, používá typ Boolean s hodnotami True a False. Jazyk JavaScript rovněž používá typ Boolean, ale jeho hodnoty jsou tentokrát pojmenovány true a false (první písmeno se píše malé).

Různé jazyky používají pro pojmenování boolovského typu mírně odlišná jména. Python mu říká bool, VBScript a JavaScript Boolean. Většinou se tím nemusíte vůbec zabývat, protože budete spíše používat boolovské výsledky v testech, než abyste je ukládali do boolovských proměnných.

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é podporují jazyky Python, VBScript a JavaScript. Nakonec stručně shrneme, s jakými dalšími typy kolekcí se můžeme setkat v jiných jazycích.

Seznam

Seznamy dobře známe z každodenního života.

Seznam (anglicky list [list]) je jednoduše tvořen posloupností položek. Do seznamu můžeme položky přidávat nebo je můžeme naopak odstraňovat. Pokud máme seznam napsaný na papíru, pak můžeme stěží vkládat položky doprostřed. Můžeme je přidávat pouze na konec. Ale pokud seznam udržujeme v elektronické podobě, dejme tomu v textovém editoru, můžeme nové položky vkládat do libovolného místa seznamu.

V seznamu můžeme také vyhledávat — pokud chceme zjistit, zda v něm něco už je, nebo ne. V takovém prípadě ale musíme seznam procházet postupně, od začátku do konce, a kontrolovat, zda se jedná o položku, kterou hledáme. Seznamy patří v mnoha moderních programovacích jazycích k základním typům s charakterem kolekce.

V jazyce Python jsou seznamy přímo jeho součástí (jsou zabudovány do jazyka). Můžeme s nimi provádět všechny základní operace, o kterých jsme se zmínili výše. Navíc můžeme položky seznamu zpřístupňovat i prostřednicvím indexu. To znamená, že k prvku seznamu můžem přistupovat na základě znalosti jeho pořadového čísla. (Prvnímu prvku je přiděleno pořadové číslo nula.)

V jazyce VBScript neexistují seznamy jako takové, ale jejich vlastnosti můžeme simulovat jinými typy kolekcí, o kterých se zmíníme později.

V jazyce JavaScript rovněž nemáme přímo typ seznam, ale téměř ke všemu, co potřebujete dělat se seznamem, můžete využít jeho typ pole (array [erey]). Jde o jiný typ kolekce, o kterém se budeme bavit o něco později.

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 — jde o seznam znaků. V jazyce Python seznam vytvoříme a zpřístupníme použitím hranatých závorek. (Tímto zápisem seznam konstruujeme, proto se takto použité dvojici hranatých závorek říká také konstruktor seznamu.) 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). Pokud například chceme zpřístupnit třetí prvek, použijeme index 2:

>>> 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]

Povšimněte si, že třetí prvek (index 2) změnil svou hodnotu z 3 na 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

Operátorem append() můžeme přidávat nové položky na konec seznamu:

>>> 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). V posledním případě 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.

Možnost vnořování seznamů jednoho do druhého je velmi užitečná. Tato vlastnost nám umožňuje budovat datové tabulky, jako je například následující:

>>> radek1 = [1, 2, 3]
>>> radek2 = ['a', 'b', 'c']
>>> tabulka = [radek1, radek2]
>>> print tabulka
[[1, 2, 3], ['a', 'b', 'c']]
>>> prvek2 = tabulka[0][1]

Tímto způsobem si můžeme vybudovat například adresář (pro ukládání adres lidí), kde každá položka představuje seznam se jménem a dalšími detaily adresy. Následující příklad uvádí adresář s dvěmi položkami:

>>> adresy = [
... ['Mirek', 'Kolbenova 15', 'Olomouc', '585 456 231'],
... ['Hanka', 'Ypsilantiho 42', 'Brno', '525 698 444']
... ]

Povšimněte si, že jsme celý zanořený seznam vytvořili zápisem na jednom řádku (je zalomen jen kvůli nedostatku prostoru — tečky znázorňují pokračování řádku). Python sleduje, zda počet uzavřených závorek odpovídá počtu otevřených. Pokud ne, pokračuje v načítání vstupu, až do doby, kdy se počty srovnají. Uvedený zápis představuje velmi efektivní způsob rychlého budování složitých datových struktur. Celková struktura — v tomto případě seznam seznamů — přitom zůstává pro čtenáře kódu přehledná.

Cvičně zkuste získat Mirkovo telefonní číslo — čtvrtý prvek z prvního řádku. Uvědomte si, že indexy začínají nulou. Zkuste přidat několik svých záznamů použitím operace append(), o které jsme se zmiňovali výše.

Jakmile Python ukončíte, vaše data budou ztracena. Až se budeme bavit o souborech, zjistíte, jak můžete data ze seznamu uložit pro další použití.

Opačnou operací k přidávání položky je, samozřejmě, rušení položky. Provedeme ji příkazem 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]

Povšimněte si, že se výsledek tentokrát liší od dříve uvedeného příkladu, kdy jsme spojovali dva seznamy operací append(). Tehdy jsme dostali seznam s dvěmi prvky, přičemž druhým prvkem byl připojovaný seznam. V tomto případě dostáváme seznam s čtyřmi prvky, protože do nového seznamu byly vloženy prvky z obou spojovaných seznamů — každý prvek samostatně. Pokud v tomto případě přistupujeme k prvku s indexem 1, nedostaneme se tentokrát k podseznamu, jak tomu bylo v předchozím případě, ale pouze k prvku s hodnotou 1:

>>> print novySeznam[1]
1

Pro naplnění seznamu více položkami se stejnou hodnotou můžeme využít operátoru pro opakování — zápis se podobá násobení:

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

Pro prvek seznamu s určitou hodnotou můžeme nalézt jeho index operací index():

>>> print [1,3,5,7].index(5)
2
>>> print [1,3,5,7].index(9)
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
ValueError: list.index(x): x not in list

Povšimněte si, že pokus o nalezení něčeho, co není prvkem seznamu, má za následek chybu. V dalších částech učebnice si ukážeme způsoby, jak lze zjistit, zda se něco v seznamu nachází, či nikoliv.

Délku seznamu (počet jeho položek) můžeme zjistit voláním zabudované funkce len():

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

Ani JavaScript ani VBScript typ seznam přímo nepodporují. Ale o kousek dál si ukážeme, že podporují typ Array (pole), se kterým lze napodobit funkčnost pythonovských seznamů.

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á uspořádaná 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. V ostatních případech lze na n-tice aplikovat většinu operací, které se používají pro seznamy.

Ačkoliv n-tici nemůžeme měnit, můžeme operátorem pro sčítání (plus) jakoby přidat další členy. Ve skutečnosti se tím totiž vytvoří nová n-tice:

>>> ntice1 = (1, 2, 3)
>>> ntice2 = ntice1 + (4,) # čárka způsobí, že se zápis chápe jako n-tice a ne jako číslo
>>> print ntice2
(1, 2, 3, 4)

Pokud bychom za číslem 4 neuvedli čárku, Python by to chápal jako zápis celého čísla uzavřeného v závorkách a ne jako zápis n-tice. Ale protože k n-ticím nelze přičítat čísla, vedlo by to k chybě. Přidáním čárky Pythonu říkáme, aby zápis v závorkách chápal jako zápis n-tice. Kdykoliv budete chtít Pythonu dát najevo, že jednoprvková n-tice skutečně je n-ticí, přidejte k zápisu čárku stejně, jako jsme to udělali zde.

VBScript ani JavaScript koncept n-tic nepodporují.

Slovník (vyhledávací tabulka)

V tištěném slovníku je k jednotlivým slovům uveden jejich význam. Podobně je tomu i u datového typu slovník (anglicky dictionary [dykšnri]), kde jsou k jednotlivým klíčům přidruženy hodnoty. Přitom hodnoty mohou, ale nemusí, mít podobu řetězce. Hodnotu můžeme získat tím, že klíč použijeme pro slovník jako index. Narozdíl od tištěného slovníku, ani klíč nemusí být znakovým řetězcem — ačkoliv řetězec se č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 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 ukažme alespoň to, 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):

>>> dct = {}
>>> dct['boolean'] = "Hodnota, která je buď True nebo False"
>>> dct['integer'] = "Celé číslo"
>>> print dct['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 — složené závorky jsou konstruktorem slovníku tak, jako jsou hranaté závorky konstruktorem seznamu nebo kulaté závorky konstruktorem n-tice). Poté používáme hranaté závorky pro přiřazování a čtení hodnot.

Slovník můžeme naplnit počátečními hodnotami v okamžiku jeho vytvoření podobně, jako jsme si to ukázali u seznamů:

>>> adresy = {
... 'Mirek' : ['Mirek', 'Kolbenova 15', 'Olomouc', '585 456 231'],
... 'Hanka' : ['Hanka', 'Ypsilantiho 42', 'Brno', '525 698 444']
... }

Klíč a hodnota se od sebe oddělují dvojtečkou a tyto páry se od dalších oddělují čárkou. Tentokrát jsme náš adresář vytvořili jako slovník, kde jsme jako klíč použili jméno a jako slovníkovou hodnotu ukládáme původní seznamy s hodnotami. Místo zjišťování a používání číselného indexu nyní můžeme potřebné informace získat na základě jména, a to takto:

>>> print adresy['Hanka']
['Hanka', 'Ypsilantiho 42', 'Brno', '525 698 444']
>>> print adresy['Mirek'][3]
585 456 231

V druhém případě jsme vrácený seznam dále indexovali, abychom obdrželi jen telefonní číslo. Práci si můžeme dále zjednodušit zavedením pomocných proměnných, které naplníme příslušnými hodnotami indexů:

>>> jmeno = 0
>>> ulice = 1
>>> mesto = 2
>>> tel = 3

Pokud nyní chceme zjistit, ve kterém městě bydlí Hanka, můžeme napsat:

>>> print adresy['Hanka'][mesto]
Brno

Povšimněte si, že zatímco jméno 'Hanka' uvádíme v apostrofech, protože jde o klíč typu řetězec, zápis mesto uvádíme bez apostrofů, protože jde o jméno proměnné, které Python převede na hodnotu indexu, kterou jsme do ní uložili (konkrétně 2). V tomto okamžiku začíná náš adresář připomínat použitelnou databázovou aplikaci. Můžeme za to poděkovat síle datového typu slovník. Moc práce nám nedá ani doplnění kódu pro ukládání a načítání dat a přidání dotazovacího řádku, přes který budeme moci určit, jaká data požadujeme. Při probírání dalších témat této učebnice si to ukážeme.

Ř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 všech klíčů, máme k dispozici operaci keys(). Ta vrací seznam všech klíčů, které seznam používá. Pokud například chceme získat seznam všech jmen z našeho adresáře, můžeme napsat:

>>> print adresy.keys()
['Hanka', 'Mirek']

Zde musíme upozornit na to, že klíče nejsou ve slovníku uloženy v pořadí, v jakém byly vkládány. Z tohoto důvodu se vám může zdát, že se objevují v nějakém divném pořadí, které se dokonce může během používání slovníku měnit. Nedělejte si s tím starosti. Nic to nemění na skutečnosti, že prostřednictvím klíčů můžete přistupovat k vašim datům. Vždy korektně obdržíte tu správnou hodnotu.

Slovníky ve VBScript

V jazyce VBScript máme k dispozici objekt typu slovník, který má podobné vlastnosti, jako slovník v jazyce Python, ale používá se trochu jinak. Nejdříve musíme deklarovat proměnnou, která bude objekt zpřístupňovat. Poté vytvoříme vlastní objekt typu slovník a nakonec do něj přidáme položky:

Dim dict               ' Vytvoříme proměnnou.
Set dict = CreateObject("Scripting.Dictionary")
dict.Add "a", "Athens" ' Přidáme nějaké položky.
dict.Add "b", "Belgrade"
dict.Add "c", "Cairo"

Povšimněte si, že ve funkci CreateObject() (tj. vytvoř objekt) uvádíme, že chceme vytvořit objekt "Scripting.Dictionary". To znamená, že chceme vytvořit objekt Dictionary (slovník), který je pro interpret VBScript definován v modulu Scripting. Podrobnostmi se zatím nebudeme zatěžovat. Dostaneme se k nim později, až se budeme zabývat objekty. Doufám, že se vám alespoň vybavuje koncepce používání objektů definovaných v modulech — zmínili jsme se o ní v podkapitole Jednoduché posloupnosti. Povšimněte si také, že při přiřazování objektu do proměnné musíme v jazyce VBScript použít klíčové slovo Set ([set] = nastavit).

Nyní můžeme k datům přistupovat takto:

item = dict.Item("c")         ' Získání hodnoty položky.
dict.Item("c") = "Casablanca" ' Změna hodnoty položky.

Kromě toho máme k dispozici i operace k odstranění položky, k získání seznamu všech klíčů, k otestování existence klíče a podobně.

Následující příklad představuje úplnou (i když trochu zjednodušenou) podobu našeho adresáře, zapsaného v jazyce VBScript:

<script type="text/vbscript">
Dim adresy
Set adresy = CreateObject("Scripting.Dictionary")
adresy.Add "Mirek", "Mirek, Kolbenova 15, Olomouc, 585 456 231" 
adresy.Add "Hanka", "Hanka, Ypsilantiho 42, Brno, 525 698 444"

MsgBox adresy.Item("Hanka")
</script>

Pro uchovávání informací tentokrát místo seznamu používáme jediný řetězec. Na ukázku zpřístupňujeme data záznamu s klíčem Hanka a zobrazujeme je v dialogovém okně.

Slovníky v JavaScript

JavaScript nemá k dispozici svůj datový typ slovník. Pokud ovšem používáte prohlížeč Internet Explorer, můžete použít objekt typu Scripting.Dictionary, který je součástí VBScript. Bavili jsme se o něm v předešlém textu. I při použití z JavaScript má naprosto stejné vlastnosti. Je to tentýž typ objektu a proto se jím zde nebudeme dále zabývat. Místo slovníků můžeme v JavaScript využít podobným způsobem typ pole — viz níže.

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

Z hlediska historie počítačů patří pole k jednomu z prvních typů kolekcí. V podstatě se jedná o seznam prvků, ke kterým lze snadno a rychle přistupovat na základě indexu. Obvykle musíme předem určit, kolik prvků má pole uchovávat. A právě pevná velikost je tím rysem, který se pole liší od seznamu, o němž byla řeč výše. V Pythonu máme typ pole k dispozici prostřednictvím modulu array. Používá se však velmi zřídka, protože místo něj můžeme obvykle použít vestavěný typ seznam.

Poznámka překladatele: Modul array umožňuje v Pythonu definovat pole pouze pro prvky základních typů a to znak, celé číslo a reálné číslo. Pro jeho použití se rozhodneme pravděpodobně jen v případě, kdy nám velmi záleží na efektivnosti použití ve smyslu výkonnějšího kódu.

V jazycích VBScript i JavaScript jsou pole k dispozici v podobě datového typu. Podívejme se, jak se používají.

Pole v jazyce VBScript

V jazyce VBScript mají pole podobu kolekce dat s pevnou délkou. K prvkům se přistupuje přes číselný index. Deklarace a přístup k prvkům se zapisují takto:

Dim pole(42)       ' Pole s 43 prvky.
pole(0) = 27       ' Indexovat se začíná od nuly.
pole(1) = 49
promenna = pole(1) ' Čtení hodnoty.

Povšimněte si, že používáme klíčové slovo Dim, které vyjadřuje, že proměnné bude přidělen paměťový prostor. Tímto způsobem interpretu VBScript řekneme, že chceme pracovat s uvedenou proměnnou. Pokud na začátku skriptu uvedeme OPTION EXPLICIT, pak bude VBScript vyžadovat, abychom klíčovým slovem Dim uvedli každou proměnnou, kterou budeme chtít používat. Řada odborníků přes programování pokládá tento přístup za žádoucí, protože věří, že vede k tvorbě spolehlivějších programů. Povšimněte si také, že v deklaraci uvádíme hodnotu posledního platného indexu — v našem případě 42. Indexovat se začíná od nuly, takže to znamená, že deklarujeme pole o 43 prvcích.

Povšimněte si také, že u jazyka VBScript používáme pro deklaraci rozměru pole a pro indexování kulaté závorky, nikoliv hranaté závorky, jak je tomu u jazyka Python (viz dále), JavaScript a u řady dalších programovacích jazyků.

Deklarovat můžeme i vícerozměrná pole — modelujeme datovou tabulku. Podobný efekt jsme si ukázali v případě pythonovských seznamů. Pro náš příklad adresáře bychom mohli psát:

Dim MojeTabulka(2, 3)              ' 3 řádky, 4 sloupce
MojeTabulka(0,0) = "Mirek"         ' Naplníme položky pro Mirka.
MojeTabulka(0,1) = "Kolbenova 15"
MojeTabulka(0,2) = "Olomouc"
MojeTabulka(0,3) = "585 456 231"
MojeTabulka(1,0) = "Hanka"         ' Naplníme položky pro Hanku.
... a tak dále...

Bohužel však neexistuje způsob, jak bychom mohli předepsat naplnění tabulky daty najednou — jak jsme to ukázali u pythonovských seznamů. Položky tabulky musíme plnit jednu po druhé. Pokud zkombinujeme vlastnosti polí a slovníků, dosáhneme pro verzi ve VBScript stejných užitkových vlastností, jako tomu bylo u pythonovské verze:

<script type="text/vbscript">
Dim adresy
Set adresy = CreateObject("Scripting.Dictionary")
Dim Mirek(3)
Mirek(0) = "Mirek"
Mirek(1) = "Kolbenova 15"
Mirek(2) = "Olomouc"
Mirek(3) = "585 456 231"
adresy.Add "Mirek", Mirek

MsgBox adresy.Item("Mirek")(3) ' Vytiskneme telefonní číslo.
</script>

Poslední věc, o které bych se chtěl zmínit, je skutečnost, že pole v jazyce VBScript nemusí mít vůbec pevnou velikost. To ovšem neznamená, že si můžeme dovolit jednoduše přidávat prvky způsobem, jak jsme to dělali u seznamů. Změnu rozměrů pole musíme předepsat příkazem. Abychom to mohli udělat, musíme pole deklarovat jako dynamické pole. Dosáhneme toho jednoduše tím, že neuvedeme jeho rozměr:

<script type="text/vbscript">
Dim DynPole()
ReDim DynPole(5)  ' Počáteční velikost.
DynPole(0) = 42
DynPole(4) = 26
MsgBox "Před: " & DynPole(4) ' Dokažme, že to funguje.

' Rozměr pole změníme na 21 prvků při zachování stávajících dat.
ReDim Preserve DynPole(20)
DynPole(15) = 73
MsgBox "Po: " & DynPole(4)   ' Hodnota byla zachována.

' Opět změníme rozměr (51 prvků), ale dojde ke ztrátě dat.
ReDim DynPole(50)
MsgBox "A ještě... " & DynPole(4) & " Kam se poděla data?"
</script>

Z příkladu je zřejmé, že použití dynamického pole není tak příjemné, jako použití seznamu, který automaticky přizpůsobuje svou délku. Na druhou stranu má ale programátor k dispozici více prostředků pro jemné ovládání chování programu. Uvedená úroveň kontroly nad chováním programu může mimo jiné zvýšit bezpečnost, protože například některé viry mohou datové struktury s dynamicky měnitelnou velikostí zneužít.

Pole v jazyce JavaScript

Typem pole (Array) je v jazyce JavaScript z mnoha pohledů vyjádřeno něco jiného, než co bychom typicky čekali. To, čemu se zde říká pole, ve skutečnosti vykazuje podivnou směsici vlastností seznamů, slovníků a klasických polí. V nejjednodušším případě můžeme pole 10 prvků nějakého typu deklarovat takto:

var pole = new Array(10);

Prvky poté můžeme naplnit a zpřístupňovat takto:

pole[4] = 42;
pole[7] = 21;
var hodnota = pole[4];

Ale typ hodnoty není u prvků pole v JavaScript omezen pouze na jediný. Do každého z prvků pole můžeme přiřadit cokoliv:

pole[9] = "Krátký řetězec.";
var zprava = pole[9];

Při vytváření pole můžeme zadat dokonce seznam položek:

var jinePole = new Array("jedna", "dvě", "tři", 4, 5, 6);
hodnota = jinePole[3];
zprava = jinePole[0];

K dalším rysům polí v jazyce JavaScript patří to, že můžeme zjistit jejich délku (počet prvků) použitím skryté vlastnosti nazvané length (tj. délka):

var velikost = pole.length

Všimněte si, formát zápisu jméno.vlastnost připomíná volání funkce z pythonovského modulu, ale bez závorek.

Jak je obvyklé i v jiných jazycích, pole se v JavaScript indexují od nuly. Nicméně v roli indexu nemusí u JavaScript vystupovat jen číslo. Můžeme použít i řetězec! V takovém případě se vlastnosti polí téměř shodují s vlastnostmi slovníků. Pole můžeme zvětšit jednoduše tím, že přiřadíme nějakou hodnotu prvku s indexem, který přesahuje aktuální maximální index. Následující kousky kódu zmíněné vlastnosti ilustrují:

pole[42] = 7;
jinePole["něco"] = 42;
zprava = jinePole["něco"]; 

A nakonec se podívejme, jak by při využití polí v JavaScript vypadal náš příklad adresáře:

<script type="text/javascript">
var adresy = new Array();
adresy["Mirek"] = "Mirek, Kolbenova 15, Olomouc, 585 456 231"; 
adresy["Hanka"] = "Hanka, Ypsilantiho 42, Brno, 525 698 444";

document.write(adresy.Hanka);
</script>

Povšimněte si, že v posledním příkazu se ke klíči chováme, jako kdyby to byla vlastnost objektu — podobně jako k výše zmíněné vlastnosti length.

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, VBScript ani JavaScript. 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é, nepropadejte panice. 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 našich jazycích se pro tento účel používají seznamy.

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.). Jazyky VBScript a JavaScript datový typ množiny přímo nepodporují, ale vlastnosti množin můžeme docela snadno napodobit použitím slovníků.

V jazyce Python jsou od verze 2.3 množiny dostupné v podobě modulu sets. Jeho implementace se považuje za experimentální. Od verze 2.4 se podpora množin stane součástí jádra jazyka. Poznámka překladatele: Zabudování do jádra jazyka bylo potvrzeno při vydání alfa verze Python 2.4. Množiny jsou implementovány v jazyce C, takže budou efektivnější, než v Python 2.3.

Základní použití množin (Python 2.3) vypadá nějak takto:

>>> import sets
>>> A = sets.Set()        # Vytvoř prázdnou množinu.
>>> B = sets.Set([1,2,3]) # Vytvož 3prvkovou množinu.
>>> C = sets.Set([3,4,5])
>>> D = sets.Set([6,7,8])
>>> # Teď si vyzkoušíme nějaké operace.
>>> B.union(C)                     # sjednocení
Set([1,2,3,4,5])
>>> B.intersection(C)              # průnik 
Set([3])
>>> B.issuperset(sets.Set([2]))    # je nadmnožinou
True
>>> sets.Set([3]).issubset(C)      # je podmnožinou
True
>>> C.intersection(D) == A         # rovnost množin
True

Výčet množinových operací je mnohem širší, ale pro tento okamžik považuji výše uvedené za dostačující.

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. K implementaci fronty se obvykle využívá pole nebo seznam.

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 pravděpodobně setkáte. (V této učebnici se ve skutečnosti budeme zabývat jen některými z výše zmíněných, ale o dalších typech se můžete dozvědět v různých článcích a v diskusních skupinách věnovaných programování.)

Poznámka překladatele k frontě: Podobně, jako v případě zásobníku, můžeme i frontu v jazyce Python 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ům počítače by vám pojem soubor měl být dobře známý, protože soubory 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 (Práce se soubory).

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. V dalších tématech se stručně seznámíme s používáním pythonovského modulu time. Jazyky VBScript i JavaScript používají pro práci s časem své vlastní mechanismy, ale těmi se zabývat nebudeme.

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 různorodých datových položek dohromady a pracovat s nimi jako s celkem. 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]) nebo její modernější, objektově orientované podoby, třídy (class [klás]).

VBScript

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

Class Adresa
     Public CisloDomu
     Public Ulice
     Public Mesto
     Public PSC
End Class

Klíčové slovo Public zajistí přístupnost dat v celém zbytku programu. Datové položky mohou být označeny také jako Private, ale k tomu se v této učebnici dostaneme až později.

Python

Zápis stejného případu v jazyce Python se příliš neliší:

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

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í zdrojového textu 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.

JavaScript

V jazyce JavaScript se pro definici struktury používá poněkud podivné jméno, a to function. Funkce si obvykle spojujeme s operacemi, ne s datovými kolekcemi, ale v případě jazyka JavaScript se funkce používají i pro tento účel. Vytváření objektu Adresa se v jazyce JavaScript zapisuje takto:

function Adresa(Dum, Ul, Mesto, PSC)
{
    this.CisloDomu = Dum;
    this.Ulice = Ul;
    this.Mesto = Mesto;
    this.PSC = PSC;
}

Zopakujme to ještě jednou. Výsledkem je skupina datových položek, na kterou se díváme jako na jeden celek.

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.

V jazyce VBScript

Pokud budeme uvažovat výše uvedenou třídu Adresa, pak bychom v jazyce VBScript mohli napsat:

Dim Adr
Set Adr = New Adresa

Adr.CisloDomu = 7
Adr.Ulice = "Havlíčkova"
Adr.Mesto = "Staré Město"
Adr.PSC = "790 58"

MsgBox Adr.Ulice & " " & Adr.CisloDomu & ", " & Adr.Mesto

Nejdříve jsme použitím klíčového slova Dim vyhradili prostor pro novou proměnnou Adr. S využitím Set vytvoříme novou instanci třídy Adresa. Poté do položek instance nového objektu adresy přiřadíme hodnoty a nakonec obsah zobrazíme v dialogovém okně pro zprávu (message box).

V jazyce Python

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

Adr = Adresa(7, "Havlíčkova", "Staré Město", "790 58")
print Adr.Ulice, Adr.CisloDomu
print Adr.Mesto 

Tím se vytvoří instance našeho typu Adresa a přiřadí se do proměnné Adr. V Pythonu můžeme předat hodnoty položek v okamžiku vytváření objektu. (Konstruktoru objektu lze předávat parametry.) Poté s využitím tečkového operátoru tiskneme složky CisloDomu, Ulice a Mesto. Můžete, samozřejmě, vytvořit více instancí třídy Adresa a do každé z nich přiřadit jiné číslo domu, ulici, a tak dále. Vyzkoušejte si to. Tušíte, jak byste mohli třídu Adresa využít pro náš příklad adresáře?

A ještě v jazyce JavaScript

Mechanismus používaný v jazyce JavaScript se velmi podobá mechanismům v ostatních jazycích. Přesto zde můžeme nalézt — jak uvidíme za chvíli — pár zvláštností. Nicméně, základní mechanismus je jednoduchý:

var Adr = new Adresa(7, "Havlíčkova", "Staré Město", "790 58");
document.write(Adr.Ulice + " " + Adr.CisloDomu + ", " + Adr.Mesto);

K zpřístupnění položek můžeme použít ještě jeden mechanismus, kdy se na objekt díváme jako na slovník a jméno pole používáme jako klíč:

document.write(Adr['Ulice'] + " " + Adr['CisloDomu'] + " " + Adr['Mesto']);

Jediný rozumný důvod k použití tohoto způsobu, který mě napadá, je ten, že jména položek získáváte za běhu programu v podobě řetězce — třeba jako výsledek čtení ze souboru nebo jako vstup zadaný uživatelem (viz dále).

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, dáme jí jméno mySpam a poté použijeme mySpam pro přístup k jejím operacím a datovým složkám takto:

>>> import meat
>>> mySpam = meat.Spam()     # vytvoření instance, užití jména modulu a třídy
>>> 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%'}

Na prvním řádku importujeme do našeho programu modul nazvaný meat (jde o fiktivní, neexistující modul). Na druhém řádku používáme modul meat k vytvoření instance třídy Spam tím, že identifikátor třídy použijeme, jako kdyby se jednalo o volání funkce. Na třetím řádku používáme jednu z operací třídy Spam, a sice slice(). K objektu mySpam se chováme, jako kdyby to byl modul a operace jako kdyby byla funkcí definovanou uvnitř modulu. Nakonec zpřístupňujeme některá data uchovávaná uvnitř objektu mySpam. Opět používáme zápis, který se podobá práci s modulem.

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ě.

S objekty můžeme pracovat i v jazycích VBScript i JavaScript. Ve výše uvedených příkladech s typem Adresa jsme ve skutečnosti nedělali nic jiného. Definovali jsme třídu, vytvořili jsme její instanci a proměnnou, přes kterou můžeme zpřístupňovat vlastnosti instance. Znovu si projděte předchozí text a zaměřte se na to, co jsme si řekli o třídách a objektech. Zamyslete se nad tím, že třídy poskytují mechanismus pro definici nových datových typů tím, že svazují dohromady data a operace.

Specifické operátory jazyka Python

Mým prvotním cílem, kterému jsem zasvětil tuto učebnici, 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, který se hodí na všechno. Python není výjimkou. 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 vnitřní části seznamu (nebo řetězce nebo n-tice — anglicky slicing [slajsing], zapisujeme spam[X:Y]) a operaci přiřazení n-tice (X, Y = 12, 34), které nám umožňuje zapsat přiřazení více hodnot více proměnným najednou. (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

Jak už jsem řekl dříve, detaily tohoto příkladu budou vysvětleny později. Někteří čtenáři však měli se zprovozněním pythonovského příkladu problémy. Tato poznámka vysvětluje jeho kód řá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 konkrétně této 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 této učebnici 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ě snadno jako vestavěné typy.

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 budou do dopisu automaticky vloženy informace o tomto HTML dokumentu.

$Id: cztutdata.html,v 1.14 2005/09/03 13:07:39 petr Exp $