O čem si budeme povídat?
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.
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.
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í.
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.
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.
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 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).
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:
'Toto je retezec'
"Toto je velmi podobny retezec"
"""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.
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).
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 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.
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>
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 — 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.
S většinou aritmetických operátorů, které budeme potřebovat, jsme se již setkali v kapitole Jednoduché posloupnosti. Zopakujme si je:
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 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
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.
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.
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í.
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í.
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.
Zápis | Jméno operace | Popis významu |
---|---|---|
A and B | A 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.
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.
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.
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ů.
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í.
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.
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ě.
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.
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í.
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.
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
.
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 (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 (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 (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.
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).
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.
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]).
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.
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.
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.
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 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 — 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?
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).
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.
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.
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 $