O čem si budeme povídat?
Čtvrtý element programování do hry zapojuje použití modulů (viz Společné vlastnosti programů). Ve skutečnosti není naprosto nezbytné a i bez něj, s použitím toho, o čem jsme se zatím bavili, můžete vytvořit docela působivé programy. Jenomže s tím, jak se program stává větším, stává se stále obtížnějším sledování toho, co a kde se v něm děje. Potřebujeme najít způsob jak potlačit nutnost uvažování o některých detailech, abychom mohli uvažovat o řešeném problému a abychom nemuseli řešit vše, co souvisí s fungováním počítače. Python, VBScript a JavaScript a další jazyky to do jisté míry řeší již svými zabudovanými schopnostmi — nemusíme se například zabývat detaily počítačového technického vybavení (hardware), nemusíme se zabývat tím, jak se čtou stisky jednotlivých kláves na klávesnici a podobně.
Používání modulů má programátorovi umožnit rozšiřování
zabudovaných schopností jazyka. Zabývá se obalováním kousků programů do
modulů tak, abychom je mohli využít v našich programech. První formou modulu
byl podprogram, což byl blok kódu, na který bylo možno skočit
(něčím jako příkaz GOTO
, o kterém jsme se zmínili v kapitole o
větvení). Jakmile byl blok dokončen, bylo možné skočit zpět do místa odkud
byl volán. Tato konkrétní podoba modularity je známa pod pojmy
procedura nebo funkce. V jazyce Python a v některých
dalších jazycích se slovo modul spojilo s přesněji vymezeným
významem, o kterém si za chvíli něco povíme. Ale nejdříve se podívejme
podrobněji na funkce.
Dříve, než se budeme zabývat tím, jak můžeme funkci vytvořit, podívejme se, jak používáme velké množství funkcí, které se k libovolnému programovacímu jazyku dodávají (často se dodávají v podobě takzvané knihovny).
Použití některých funkcí a seznam dalších funkcí jsme již viděli, když jsme se bavili o operátorech. Nyní se zaměříme na to, co mají všechny funkce společné a jak je můžeme používat v našich programech. Základní struktura volání funkce vypadá následovně:
Promenna = nejakaFunkce(argument, dalsi, atd...)
To znamená, že proměnné Promenna
je přiřazena hodnota, která
je získána jako výsledek volání funkce. Funkce může mít žádný nebo více
argumentů, ke kterým se chová jako k interním proměnným. Funkce
mohou uvnitř svého kódu volat další funkce. Ve většině programovacích jazyků
(i když ne ve všech) musíme v zápisu volání funkce uvádět závorky i v
případě, kdy nemá žádné argumenty.
Vezměme si některé příklady v našich vybraných jazycích a podívejme se, jak to funguje:
Tato funkce vrací delka
znaků z řetězce retezec
,
počínaje pozicí start
.
<script type="text/vbscript"> Dim cas cas = "ráno večer odpoledne" MsgBox "Dobrý " & Mid(cas, 6, 5) </script>
Zobrazí se "Dobrý večer". Poznamenejme, že u VBScript se argumenty funkce nemusí uzavírat do závorek — stačí oddělení mezerou.
Tato funkce vrací aktuální systémové datum.
<script type="text/vbscript"> MsgBox Date </script>
Asi už se k tomu nedá víc dodat. Snad jen, že existuje celá skupina funkcí pro práci s datem, které umožňují získat informaci o dni, týdnu, hodině atd.
Vrací nový řetězec, který vznikne z řetězce <startString>
nahrazením podřetězce searchString
novým řetězcem
newString
.
<script type="text/javascript"> var r, s = "Dlouhá a vítězná cesta."; document.write("Originál = " + s + "<BR>"); r = s.replace("Dlouhá", "Krátká"); document.write("Výsledek = " + r); </script>
Poznámka: V jazyce JavaScript se téměř všude
setkáváme se speciálním typem funkce, které říkáme metoda. Metodou
rozumíme funkci, která je spojena s objektem (viz dříve probírané
téma Data, datové typy a proměnné a viz
více detailů dále). Za poznámku zde stojí především to, že uvedená funkce je
připojena k řetězci s
tečkovým operátorem. Chápe se to
tak, že s
je řetězcem, nad kterým se provádí náhrada.
Není to nic nového. Už od začátku této učebnice používáme pro zobrazení
výstupu v našich javascriptových programech metodu write()
objektu document
(zapisujeme document.write()
).
Zatím jsem se pouze nezmiňoval o důvodech, které jsou s touto formou zápisu
spojeny.
Funkce pow()
umocňuje základ x
na
y
.
>>> x = 2 # použijeme 2 jako hodnotu základu >>> for y in range(0, 11): ... print pow(x, y) # umocní 2 na y, tj. na 0 až 10
V tomto příkladu generujeme hodnoty y
od 0 do 10 a voláme
zabudovanou funkci pow()
s předáváme jí dva argumenty:
x
a y
. Aktuální hodnoty x
a
y
jsou do volání funkce pow()
dosazeny při každé
obrátce cyklu a výsledek je pokaždé vytištěn.
Poznámka: Python definuje také operátor pro umocňování
**
, který je ekvivalentem funkce pow()
.
Další užitečnou zabudovanou funkcí jazyka Python je funkce
dir()
. Když jí předáme jméno modulu, vrátí nám seznam platných
jmen — často jsou to jména funkcí —, které modul obsahuje.
Vyzkoušejte si ji pro vypsání seznamu jmen zabudovaných funkcí:
print dir(__builtins__)
Poznámka: Pokud budete chtít učinit totéž pro libovolný jiný modul,
musíte jej nejdříve zpřístupnit příkazem import
. V opačném
případě si Python bude stěžovat, že jméno modulu nezná.
>>> import sys >>> dir(sys)
Vzpomeňte si, že s modulem sys
jsme se setkali již v našich
prvních tématech, věnovaných posloupnostem. Python se dodává z celou řadou
modulů, ačkoliv jsme se o tom zatím nezmiňovali. Ve výstupním seznamu
posledního volání funkce dir
si můžete povšimnout naší staré
známé metody exit
.
Dříve, než se pustíme do dalších věcí, měli bychom si o modulech v jazyce Python říci více podrobností.
Python je extrémně rozšiřovatelný jazyk v tom smyslu, že můžete přidávat
nové možnosti tím, že provedete import
potřebných modulů.
Zakrátko si ukážeme, jak můžeme moduly vytvářet. Ale nejdříve si trochu
pohrajeme z některými standardními moduly, se kterými se Python již
dodává.
S modulem sys
jsme se již potkali v okamžiku, kdy jsme z
kódu v jazyce Python volali funkci exit
za účelem ukončení
programu. Modul obsahuje celou řadu dalších užitečných funkcí — jak
jsme si mohli povšimnout ve výstupu funkce dir
ve výše uvedeném
příkladu. Abychom k nim získali přístup, musíme provést příkaz
import sys
:
import sys # zpřístupní vnitřní funkce print sys.path() # ukaž, kde Python hledá moduly sys.exit() # uvádíme předponu 'sys'
Pokud víme, že budeme funkce modulu používat velmi často a pokud nemají stejná jména jako funkce, které jsme již dříve importovali nebo vytvořili, pak můžeme psát:
from sys import * # import všech jmen z modulu sys print path() # nyní nemusíme uvádět předponu 'sys' exit()
Pokud chceme z modulu používat jen pár funkcí, pak bývá bezpečnější použít následující obrat:
from sys import path, exit # importujeme jen potřebné print path() # používáme bez předpony 'sys' exit()
Povšimněte si, že za jmény vybraných funkcí neuvádíme závorky. Pokud bychom tak učinili, bylo by to chápáno jako pokus o spuštění funkcí. Uvádíme pouze jméno funkce.
Poznámka překladatele: příkaz
from...import...
je obecný a dá se použít pro zveřejnění
různých jmen definovaných v modulu, nejen jmen funkcí. Vynechávání závorek
je proto logické i z tohoto pohledu.
Uvedeným způsobem můžeme importovat libovolné pythonovské moduly. Týká se to i modulů, které si sami vytvoříte. Za okamžik si ukážeme, jak na to. Ale nejdříve si uděláme krátkou přehlídku některých standardních modulů jazyka Python a představíme si něco z toho, co nabízejí:
Jméno modulu | Popis |
---|---|
sys |
Umožňuje interakci se systémem Python:
|
os |
Umožňuje interakci s operačním systémem:
|
re |
Umožňuje manipulaci s řetězci předepsanou regulárními výrazy, jaké se
používají v systému Unix:
|
math |
Zpřístupňuje řadu matematických funkcí:
|
time |
Funkce pro práci s časem a datem:
|
random |
Generátory náhodných čísel — užitečné nejen pro programování her!
|
Uvedené funkce představují pouze špičku ledovce. V distribuci systému Python se nacházejí doslova tucty modulů a mnoho dalších si můžete stáhnout z Internetu (jejich dobrým zdrojem jsou stránky Vaults of Parnassus). Nahlédněte do dokumentace a najdete informace o funcích pro přístup na Internet, pro grafiku, pro tvorbu databází, atd.
Je důležité si uvědomit, že u většiny programovacích jazyků jsou tyto funkce buď zabudované nebo jsou součástí jejich standardní knihovny. Než začnete psát nějakou funkci, vždycky si v dokumentaci ověřte, zda již náhodou neexistuje. Tím jsme se pěkně dostali k tématu…
Nyní již víme, jak používat existující funkce a moduly. Ale jak můžeme vytvořit novou funkci? Jednoduše ji definujeme. To znamená, že napíšeme příkaz, který interpretu říká, že definujeme blok kódu, který může být na požádání proveden na jiném místě našeho programu.
Vytvořme funkci, která nám vytiskne tabulku násobků libovolného čísla, které zadáme jako argument. V jazyce VBScript by to vypadalo takto:
<script type="text/vbscript"> Sub Nasobky(N) Dim I For I = 1 To 12 MsgBox I & " x " & N & " = " & I * N Next End Sub </script>
Za značkou uvádějící blok v jazyce VBScript jsme použili klíčové slovo
Sub
(jako Subroutine, čili podprogram) a celou
definice jsme ukončili klíčovými slovy End Sub
. V kulatých
závorkách jsme uvedli seznam formálních parametrů. Uvnitř se
nachází běžný kód v jazyce VBScript až na to, že se parametry chápou jako
kdyby to byly již definované lokální proměnné.
Nově definovanou funkci můžeme od tohoto okamžiku volat třeba takto:
<script type="text/vbscript"> MsgBox "Následují hodnoty násobků čísla 7..." Nasobky 7 </script>
Poznámka 1: V uvedené funkci jsme definovali parametr
označený N
a při jejím volání jsme předali argument
o hodnotě 7
. Když je funkce zavolána, pak její lokální
proměnná N
získá hodnotu 7
. U funkce můžeme
definovat tolik parametrů, kolik potřebujeme. Při jejím volání ale musí být
každému parametru přiřazena hodnota. Některé programovací jazyky vám
umožňují definovat přednastavené hodnoty parametrů (default value),
takže pokud není jejich hodnota při volání určena, použije se přednastavená
hodnota. (V odborné
terminologii se používá pojem implicitní hodnota parametru, která
se použije, pokud hodnota parametru není explicitně určena.)
Za chvíli si ukážeme, jak se to dělá v jazyce Python.
Poznámka 2: V definici funkce je parametr
N
uzavřen v kulatých závorkách, ale — jak je u VBScript
zvykem — při volání funkce jsme kulaté závorky nepoužili.
Uvedená funkce nevrací žádnou hodnotu a je ve skutečnosti tím, čemu se říká procedura. Je to jednoduše funkce, která nevrací hodnotu. Jazyk VBScript procedury a funkce rozlišuje. Syntakticky tak činí používáním jiného klíčového slova v definici. Podívejme se na zápis skutečné funkce zapsané v jazyke VBScript, která vrací tabulku násobku jako jeden dlouhý řetězec:
<script type="text/vbscript"> Function TabulkaNasobku(N) Dim I, S S = "Tabukla násobků čísla " & N & ":" & vbNewLine For I = 1 to 12 S = S & I & " x " & N & " = " & I * N & vbNewLine Next TabulkaNasobku = S End Function Dim Nasobitel Nasobitel = InputBox("Zadejte násobitele, pro který má být tabulka generována:?") MsgBox TabulkaNasobku(Nasobitel) </script>
Zápis funkce (používá klíčové slovo
Function
) je téměř stejný, jako zápis procedury (klíčové slovo
Sub
). Ale všimněte si, že uvnitř definice funkce musíme navíc
výsledek přiřadit jménu funkce. Jakmile funkce skončí, vrátí hodnotu, která
byla jejímu jménu přiřazena:
... TabulkaNasobku = S End Function
Pokud neprovedeme přiřazení konkrétní hodnoty, funkce vrátí implicitní hodnotu (default), což je obvykle nula nebo prázdný řetězec.
Povšimněte si také, že jsme na řádku MsgBox
museli argument
uzavřít do kulatých závorek. Kdybychom tak neučinili, funkce
MsgBox
by neuměla rozlišit, zda se má Nasobitel
vytisknout, nebo zda se má předat funkci TabulkaNasobku
jako
první argument.
V jazyce Python by funkce pro tisk tabulky násobků vypadala takto:
def nasobky(n): for i in range(1, 13): print "%d x %d = %d" % (i, n, i*n)
A volali bychom ji takto:
print "Tady je tabulka násobků číslem 9 ..." nasobky(9)
Poznámka překladatele: Místo funkce
range()
by se měla přednostně používat funkce efektivnější
funkce xrange()
. Funkce range()
nejdříve
vygeneruje celý seznam čísel a teprve ten se prochází v cyklu
for
. Funkce xrange()
existenci seznamu při použití
v cyklu for
simuluje (vrací vždy další hodnotu), ale seznam
nevytváří. Důležité je to zejména při generování velkého rozsahu indexů. Ve
vzdálené budoucnosti se implementace range()
změní na něco
podobného xrange()
. Do té doby používejte přednostně
xrange()
. V jednoduchých případech funguje stejně jako
range()
, v extrémních případech je výkonnější a paměťově
nenáročná.
Povšimněte si, že v jazyce Python se mezi procedurami a funkcemi nedělá
rozdíl. Při jejich definici se používá stejné klíčové slovo
def
. Jediný rozdíl spočívá v tom, že se k návratu funkční
hodnoty používá příkaz return
:
def tabulkaNasobku(n): s = "" for i in range(1, 13): s = s + "%d x %d = %d\n" % (i, n, i*n) return s
Jak vidíte, je to velmi jednoduché. Výsledek prostě vrátíme příkazem
return
.
Možná si vzpomenete, že jsem se již zmínil o použití implicitních hodnot (default). U funkcí můžeme předepsat implicitní hodnotu parametru, který nebyl při volání funkce zadán přímo (explicitně). Smysluplnou ukázku tohoto rysu může představovat funkce, která vrací den v týdnu. Pokud ji zavoláme bez parametru, míníme tím dnes. V ostatních případech předáváme požadovaný den číslem:
# -*- coding: cp1250 -*-
import time
# Hodnota dne -1 znamená 'dnes'.
def denTydne(CisloDne = -1):
# Výčet dnů musí být uveden v pořadí, v jakém je používá Python.
dny = [u'pondělí', u'úterý',
u'středa', u'čtvrtek',
u'pátek', u'sobota', u'neděle']
# Zkontrolujeme, zda nejde o přednastavenou hodnotu.
if CisloDne == -1:
# Použij funkce modulu time
k získání současného času
# -- viz oficiální dokumentace modulu.
cas = time.localtime(time.time())
CisloDne = cas[6] # získáme číslo dne
return dny[CisloDne]
Poznámka: Modul time
potřebujeme použít jen v
případě, kdy se uplatní přednastavená (implicitní) hodnota parametru.
Operaci import
bychom proto mohli odložit až na dobu, kdy modul
skutečně potřebujeme. V případech, kdy přednastavená hodnota není nikdy
použita, by pak náš program mohl být o něco výkonnější. Ale úspora výkonu by
byla velmi malá a navíc bychom porušili konvenci, která říká, že import máme
uvádět na začátku souboru. V podobných případech raději dáme přednost vyšší
přehlednosti zdrojového textu před zanedbatelně vyšším výkonem při běhu.
Poznámka překladatele: Úvodní řádek # -*- coding: cp1250 -*-
říká, že
zdrojový text v souboru byl pořízen v kódování 1250 (přesněji
windows-1250
, ale Python vyžaduje uvedený tvar zápisu). Pokud
jej neuvedeme, bude si Python při překladu stěžovat, že nalezl znaky s kódem
větším než 128 (tj. mimo ASCII).
Nyní můžeme funkci zavolat:
print "Dnes je %s." % denTydne()
# Zapamatujte si, že v počítačové řeči začínáme nulou.
# Nula odpovídá prvnímu dni -- pondělí.
print "Třetím dnem je %s." % denTydne(2)
Jako další příklad funkce, která vrací hodnotu, si uvedeme funkci počítající slova v zadaném řetězci. Mohli bychom ji použít i pro zjištění počtu slov v souboru tak, že bychom sečetli počty slov za jednotlivé řádky. Kód by mohl vypadat nějak takto:
def pocetSlov(s): s = s.strip() # odstraníme mezery na začátku a na konci seznam = s.split() # seznam, kde prvkem je vždy slovo return len(seznam) # vrátíme počet prvků seznamu
Tím jsme nadefinovali funkci, která využívá některé metody zabudovaného typu řetězec. Zmínili jsme se o něm v kapitole Data, datové typy a proměnné. Teď bychom funkci rádi použili nějak takto:
for radek in soubor:
celkem = celkem + pocetSlov(radek) # sečti počty za každý řádek
print "Soubor má %d slov." % celkem
Pokud byste uvedený kód vyzkoušeli, zjistili byste, že nefunguje. To, co jsme si právě předvedli, je běžná technika návrhu programu. Spočívá v načrtnutí našich představ o tom, jak by kód měl vypadat, ale netrápíme se s tím, aby byl kód absolutně správný. Takovému zápisu se někdy říká pseudo kód nebo — při dodržení formálnějšího stylu — zápis v jazyce pro popis programu (z anglického Program Description Language nebo zkráceně PDL).
Až se blíže podíváme na práci se soubory a s řetězci (v další části učebnice), vrátíme se k tomuto příkladu a přepíšeme jej do funkční podoby.
V jazyce JavaScript můžeme vytvářet funkce samozřejmě také. Používáme k
tomu příkaz function
:
<script type="text/javascript">
var i, hodnoty;
function nasobky(m) {
var vysledky = new Array();
for (i = 1; i <= 12; ++i) {
vysledky[i] = i * m;
}
return vysledky;
}
// Použití funkce.
hodnoty = nasobky(8);
for (i = 1; i <= 12; ++i) {
document.write(hodnoty[i] + "<br>");
}
</script>
V tomto případě není uvedená funkce příliš užitečná. Přesto doufám, že jste si všimli podobnosti její základní struktury s definicemi funkcí v jazycích Python a VBScript. Se složitějšími funkcemi v jazyce JavaScript se setkáme v dalších částech učebnice. Zmiňme se například o tom, že v JavaScript se funkce používají jednak jako funkce a jednak k definici objektů. Zní to zmateně a ke zmatkům zde také může docházet.
Než se pustíme do dalších věcí, podívejme se zpět na příklad v JavaScript, který jsme si uvedli v kapitole Konverzace s uživatelem. Právě teď k tomu nastal ten správný čas. JavaScript jsme v něm použili pro čtení vstupu z webového formuláře. Kód vypadal takto:
<script type="text/javascript"> function mujProgram(){ alert("Získali jsme hodnotu " + document.formular.pole.value); } </script> <form name='formular'> <p>Zadej hodnotu a potom klikni myší mimo vstupní pole</p> <input type='text' name='pole' onChange='mujProgram()'> </form>
Když se na to podíváme s našimi nově nabytými znalostmi, vidíme, že jsme
nadefinovali funkci nazvanou mujProgram
. Ve formuláři jsme
předepsali, že se tato funkce má zavolat, když ze změní obsah vstupního
pole
. Další vysvětlení si uvedeme v tématu Událostmi řízené programování.
Možnost definovat funkce představuje mocný nástroj, protože nám to umožňuje rozšiřovat schopnosti jazyka. Můžeme dokonce změnit chování jazyka tím, že pro předdefinované funkce uvedeme novou definici, s novým významem (některé jazyky to neumožňují). Obvykle se to nepovažuje za příliš dobrý nápad. Každopádně musíme velmi pečlivě kontrolovat dopady podobného činu (za chvíli si ukážeme, jak na to). Předefinováním chování standardních funkcí daného jazyka můžeme velmi ztížit srozumitelnost zdrojových textů. Čtenář očekává, že se taková funkce chová určitým způsobem, ale vy jste toto chování změnili. V praxi se proto změna základního chování zabudovaných funkcí považuje za nevhodnou.
Jedna z možností, jak dodržet zásadu neměnit chování zabudovaných funkcí a přitom použít jméno funkce pro naše vlastní účely, spočívá ve vložení nové definice do objektu nebo do modulu, které platnost takové funkce definují ve svém vlastním kontextu. K objektové variantě se dostaneme později — v tématu Objektově orientované programování. Nyní se podívejme na možnost vytvoření našich vlastních modulů.
Zatím jsme si ukázali, jak můžeme vytvářet naše vlastní funkce a volat je z jiných částí našeho programu. Vytváření vlastních funkcí nám ušetří hodně psaní a — což je mnohem důležitější — učiní naše programy srozumitelnějšími. Je to dáno tím, že do vytvořených funkcí ukryjeme některé detaily, na které pak při jejich použití nemusíme myslet. (Tento princip obalování složitých úseků programu funkcemi se z docela zřejmých důvodů nazývá ukrývání informací [information hiding].) Ale jak můžeme tyto funkce používat v jiných programech? Odpověď zní — vytvoříme modul.
V jazyce Python není modul ničím zvláštním. Je to prostý textový soubor s příkazy programu v jazyce Python. Obvykle jsou to definice funkcí. Takže, když napíšeme…
import sys
tak tím interpretu jazyka Python říkáme, že má načíst obsah tohoto
modulu, provést inicializaci jeho kódu a zpřístupnit jeho vygenerovaná jména
pro použití v našem souboru. Je to téměř jako kdybychom okopírovali
obsah souboru sys.py
do našeho souboru například přes schránku
(clipboard) operacemi Kopírovat a Vložit (copy/paste). (No, ve skutečnosti
to takhle není, ale koncepčně to můžeme tak chápat.) Překladače některých
jazyků (z význačných jmenujme C a C++) kopírují na základě požadavků obsah
souborů s moduly do aktuálního programu doslova[1].
Takže si to zrekapitulujme. Modul vznikne vytvořením pythonovského
souboru (.py
), který obsahuje funkce, které chceme používat v
jiných programech. Potom jednoduše provedeme import
našeho
modulu přesně stejným způsobem, jako to děláme se standardními moduly.
Snadné, co? Tak pojďme na to.
Okopírujte si níže uvedenou funkci a uložte ji do svého souboru se jménem
nasobky.py
. Můžeme to provést prostřednictvím editoru z IDLE,
editoru Notepad (Poznámkový blok) nebo jiného editoru, který ukládá prosté
textové soubory. Nepoužívejte aplikace typu textový procesor (nepoužívejte tedy
například Microsoft Word nebo Microsoft WordPad), protože ty navíc do
souboru ukládají všelijaké formátovací značky, kterým by Python
nerozuměl.
def tisk_tabulky(nasobitel): print "--- Tisk tabulky násobků číslem %d ---" % nasobitel for n in range(1, 13): print "%d x %d = %d" % (n, nasobitel, n * nasobitel)
Nyní na příkazový řádek systému Python napište:
>>> import nasobky >>> nasobky.tisk_tabulky(12)
No vida! Právě jste vytvořili modul a použili jste ho.
Důležitá poznámka: Pokud jste Python nespustili ze stejného
adresáře, ve kterém je uložen váš soubor nasobky.py
, pak jej
Python možná nenašel a zahlásil chybu. Pokud tomu tak skutečně je, můžete
vytvořit proměnnou prostředí nazvanou PYTHONPATH
, která
obsahuje seznam adresářů, ve kterých se budou hledat moduly (tedy ty, které
nejsou dodávány jako standardní spolu se sytémem Python).
Způsob vytváření proměnných prostředí je závislý na platformě. Předpokládám, že příslušné operace buď znáte nebo si je umíte zjistit. Například uživatelé Windows XP mohou použít tlačítko Start a najít si informace o proměnných prostředí. Dozví se, jak si je mohou vytvářet. Poznámka překladatele: Konkrétně lze po stisku Start vybrat položky Nastavení — Ovládací panely, poklepat na ikonu Systém, přepnout se na záložku Upřesnit a stisknout tlačítko Proměnné prostředí. Další podrobnosti viz dokumentace.
A jak je na tom VBScript? Tady to bude složitější. V samotném jazyce VBScript a v dalších starších variantách jazyka BASIC koncepce modulu vůbec neexistuje. VBScript místo toho staví na opakovaném použití kódu mezi objekty, který je založen na vytváření objektů. Dostaneme se k tomu později. Prozatím budeme muset potřebný kód okopírovat z dřívějších projektů do aktuálního projektu pomocí funkcí textového editoru.
Poznámka: Větší bratr jazyka VBScript — jazyk
Visual Basic — ovšem koncept modulu podporuje. Modul můžeme načíst
příkazem menu File|Open Module...
v integrovaném vývojovém prostředí
(IDE). Pro moduly jazyka Visual Basic existují určitá omezení v
tom smyslu, že do něj nemůžeme umístit cokoliv. Do detailů se zde pouštět
nebudeme, protože se zde tímto jazykem nezabýváme. (Pokud chcete
experimentovat, existuje (nebo alespoň tomu tak bylo) volně dostupná verze
jazyka Visual Basic, která je známa jako Visual Basic 5.0 Control
Creation Edition, čili VBCCE. Dala se zdarma stáhnout ze
stránek společnosti Microsoft.
JavaScript (podobně jako VBScript) nenabízí žádný mechanismus pro používání modulů v podobě souborů s kódem. Ale existují zde určité výjimky a to ve specializovaných prostředích, kde se JavaScript nepoužívá jen uvnitř webových stránek. Jde například o Windows Script Host — viz dále.
Prozatím jsme se na jazyky VBScript a JavaScript dívali jako na jazyky pro programování uvnitř webového prohlížeče. Ten si však vynucuje určitá omezení, včetně nemožnosti používat moduly. V prostředí Microsoft Windows však existuje i jiný způsob používání VBScript (a JavaScript), konkrétně Windows Script Host, zkráceně WSH. Jde o technologii firmy Microsoft, která uživatelům umožňuje programovat své osobní počítače stejným způsobem, jakým programátoři v systému DOS používali dávkové soubory (s příponou .bat). WSH poskytuje mechanismy pro čtení ze souborů, ze systémového registru, umožňuje přístup k počítačům v síti, k tiskárnám, atd.
WSH verze 2 navíc umožňuje používat (include) jiný WSH soubor, takže
zavádí možnost používání modulů. Ukažme si, jak to funguje. Nejdříve si
vytvoříme soubor modulu nazvaný NejakyModul.vbs
, který
obsahuje:
Function OdectiDvojku(N) OdectiDvojku = N - 2 End Function
Teď vytvoříme WSH skript, který nazveme například
testModulu.wsf
:
<?xml version="1.0" encoding="UTF-8" ?> <job> <script language="VBScript" src="NejakyModul.vbs" /> <script language="VBScript"> Dim hodnota, vysledek WScript.Echo "Vložte číslo" hodnota = WScript.StdIn.ReadLine vysledek = OdectiDvojku(CInt(hodnota)) WScript.Echo "Výsledek je " & CStr(vysledek) </script> </job>
Poznámka překladatele 1: V originálním textu není
v prologu na prvním řádku dokumentu uvedeno kódování, v jakém byl soubor
uložen. V takovém případě se předpokládá, že je použito kódování UTF-8 nebo
UTF-16. V případě, že se v dokumentu vyskytují pouze ASCII znaky, je obsah
dokumentu v kódování UTF-8 totožný s obsahem užívajícím kódováním ASCII. U
českých dokumentů se ale objeví znaky s kódem větším, než 127. V takovém
případě je nutné dokument skutečně uložit v kódování UTF-8 (musí to umět
editor), protože některé znaky budou uloženy speciálním způsobem. V hlavičce
můžete uvést také jiné kódování, (windows-1250
,
ISO-8859-2
a podobně). Pak musíte dokument v tomto kódování
skutečně uložit. U českých dokumentů se dá obecně říci, že je vhodnější v
prologu kódování uvádět.
Poznámka překladatele 2: Narozdíl od HTML, které
pro předpis jazyka v elementu <script ...>
předepisuje
atribut type="text/jazyk"
, v XML předpisu pro WSH se
uvádí forma language="jazyk"
, která se kdysi používala
i v HTML.
Teď to můžeme spustit v DOSovém okně:
C:\> cscript testModulu.wsf
Soubor .wsf
na sebe bere podobu XML souboru. Program se
nachází mezi značkami <job>
a </job>
. První
značka <script ... />
odkazuje na soubor modulu
s názem NejakyModul.vbs
. Druhá značka
<script ...>
obsahuje náš program, který volá funkci
OdectiDvojku()
, definovanou v modulu
NejakyModul.vbs
. (První ze značek script
je
nepárová — její zápis končí />
. Veškeré informace jsou
zapsány uvnitř této značky. Naopak druhý element script
je
vymezen dvěmi značkami, které obklopují příslušný obsah.) Soubor s
příponou .vbs
obsahuje běžný kód v jazyce VBScript bez
jakýchkoliv XML či HTML značek.
Povšimněte si příkazu WScript.Echo
, ve kterém spojujeme
řetězce. Znak ampersand jsme museli zapsat zvláštním způsobem (escape), a
sice &
, protože příkaz je součástí XML souboru.
Povšimněte si také, že ke čtení vstupu od uživatele používáme
WScript.Stdin
. Vzpomínáte si na poznámku o stdin a
stdout
v tématu Konverzace s
uživatelem?
Poznámka překladatele: Pozor! Vytvořený soubor
musíme skutečně spustit přes cscript
na příkazovém řádku.
Určitou činnost sice můžeme pozorovat i při prostém poklepání na ikonu
.wsf
souboru, ale v tomto případě by došlo ke spuštění v
okénkovém režimu. Příkaz WScript.Echo
by se projevil v podobě
okna se zprávou a tlačítkem OK (Message Box).
Nemáme ale vytvořenou vazbu na WScript.Stdin
a nepodaří se nám
zadat vstupní hodnotu. Po stisku tlačítka OK se
objeví okno s chybovým hlášením a program skončí.
Stejnou techniku můžeme použít i pro JavaScript, přesněji řečeno pro
verzi jazyka JavaScript firmy Microsoft, která se nazývá JScript.
Stačí změnit atribut značky script
, který
určuje jazyk. Při použití WSH můžeme dokonce jazyky míchat. Můžeme
importovat moduly v JavaScript a používat je v kódu VBScript a naopak. Jako
důkaz si uvedeme odpovídající WSH skript, který přistupuje k VBScriptovému
modulu z JavaScriptu:
<?xml version="1.0" encoding="UTF-8" ?> <job> <script language="VBScript" src="NejakyModul.vbs" /> <script language="JScript"> var hodnota, vysledek; WScript.Echo("Vložte číslo"); hodnota = WScript.StdIn.ReadLine(); vysledek = OdectiDvojku(parseInt(hodnota)); WScript.Echo("Výsledek je " + vysledek); </script> </job>
Vídíte, jak moc jsou si obě verze podobné? Většina chytrých věcí se vlastně dělá přes objekty WScript a až na těch pár závorek a středníků jsou skripty v podstatě stejné.
V této učebnici nebudeme WSH používat příliš často. Přesto se k němu občas uchýlíme a sice v situacích, kdy nám více omezující prostředí webového prohlížeče neumožní demonstrovat některé vlastnosti. Tak například v dalším tématu s pomocí WSH ukážeme jak lze v jazycích VBScript a JavaScript pracovat se soubory. Pokud máte zájem, pak o WSH bylo napsáno pár knih. Je mu věnována rozsáhlá sekce webového serveru firmy Microsoft. Naleznete tam i ukázky programů, vývojové nástroje, atd. Vše se nachází zde: http://msdn.microsoft.com/scripting/.
V další části se podíváme na soubory a na zpracování textu. A potom, jak jsme si slíbili, se znovu podíváme na problém počítání slov v souboru. Ve skutečnosti si nakonec pro naše potřeby vytvoříme modul s funkcemi pro zpracování textu.
Zapamatujte si
def
.Sub
nebo Function
, v jazyce JavaScript se
používá function
.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: cztutfunc.html,v 1.9 2005/08/02 19:43:50 petr Exp $