Níže uvedený text pochází z prvního vydání. Nad tímto textem se nachází aktuální stav po revizi sm>řující k druhému vydání.
Už slyším, jak se ptáte… Co to je ten prostor jmen (namespace)? No, dá se to t>žko vysv>tlit. Ne proto, že by to bylo n>jak zvlášť komplikované, ale spíš proto, že se k tomu každý jazyk staví trochu jinak. Samotný koncept je docela přímočarý. Prostor jmen je prostor nebo oblast uvnitř programu, kde je jméno (prom>nné, třídy, atd.) platné.
Dřív>jší programovací jazyky (jako třeba BASIC) pracovaly pouze s globálními prom>nnými, to znamená s takovými prom>nnými, které byly vid>t z celého programu — dokonce uvnitř funkcí. To činilo udržovatelnost programů velmi obtížnou, protože pro každý kousek programu bylo velmi snadné zm>nit n>jakou prom>nnou, aniž by se to ostatní části programu n>jak dozv>d>ly. Tomuto jevu se říká vedlejší efekt. Nov>jší jazyky (včetn> moderních verzí jazyka BASIC) tento problém obcházejí zavedením prostorů jmen. (Jazyk C++ jde v tomto sm>ru do extrému tím, že umožňuje programátorovi vytvořit svůj vlastní prostor jmen kdekoliv uvnitř programu. To ocení zvlášt> tvůrci knihoven, kteří cht>jí dosáhnout jednoznačnosti jmen svých funkcí i v případ>, kdy se současn> použijí knihovny jiných tvůrců.)
V systému Python vytváří každý modul svůj vlastní prostor jmen. Pokud
chceme používat jména jeho částí, musíme jim buď předřadit jméno modulu,
nebo musíme explicitn> importovat požadovaná jména dovniř prostoru jmen
našeho modulu. Není to pro nás nic nového. Už jsme to d>lali při práci s
moduly sys a string. V určitém smyslu vytváří svůj
prostor jmen i definice třídy. Takže pokud chceme zpřístupnit metodu nebo
vlastnost třídy, musíme nejdříve použít jméno instance nebo třídy.
V Pythonu existují jen 3 prostory jmen (nebo rozsahy platnosti — scopes):
No dobrá. Ale jak to vše dáme dohromady, když prom>nné v různých
prostorech jmen mají stejné jméno? A nebo, jak se odkazujeme na jméno, které
se nenachází v aktuálním prostoru jmen? Podívejme se nejdříve na první
případ: Pokud se funkce odvolává na prom>nnou nazvanou X a
uvnitř funkce existuje n>jaká prom>nná X (tj. uvnitř prostoru s
lokálními prom>nnými), pak to bude práv> tato lokální prom>nná, kterou
Python uvidí a použije. Je v>cí programátora, aby se vyhnul střetům jmen,
kdy má n>jaká lokální prom>nná stejné jméno jako prom>nná modulu a kdy
bychom mohli chtít zpřístupnit ob> najednou. Existence lokální prom>nné v
takovém případ> maskuje existenci globální prom>nné.
Obecn> bychom m>li globální prom>nné používat co nejmén>. Obvykle bývá lepší, když b>žnou, lokální prom>nnou předáváme jako parametr volané funkce a vrací se nám s modifikovaným obsahem.
Poznámka překladatele ke globálním prom>nným: Z pohledu začátečníka se může zdát používání globálních prom>nných velmi výhodné. Jednoduše přece uvedeme jméno prom>nné, které je známé ve všech místech programu! V čem je problém? Postupn> zjistíte, že t>ch problémů může být hned n>kolik. Zdánlivá jednoduchost může pozd>ji v>ci zkomplikovat:
Druhý případ, kdy se odkazujeme na jméno, které se nenachází mezi lokálními, se řeší následujícím způsobem: Funkce prohlédne svůj lokální prostor. Pokud zde požadované jméno nenalezne, hledá v prostoru modulu. A pokud není nalezeno ani zde, hledá se v prostoru zabudovaných jmen (builtin scope). Jediná nepříjemnost nastane v situaci, kdy chceme přiřadit hodnotu externí prom>nné. Při normálním postupu by vznikla nová prom>nná tohoto jména, ale tomu se chceme vyhnout. Takže aby se nevytvořila lokální prom>nná daného jména, musíme určit, že se jedná o jméno globální.
Vše si ukážeme v akci na následujícím příkladu (jde o čist> ilustrační příklad):
# Prom>nné na úrovni modulu. W = 5 Y = 3 # Parametry se chovají jako prom>nné náležející funkci. Takže X patří # do lokálního prostoru. def spam(X): # Funkci oznámíme, že má W hledat na úrovni modulu a nevytvářet svou # prom>nnou W. global W Z = X*2 # Nová prom>nná Z je vytvořena jako lokální. W = X+5 # Práce s W na úrovni modulu -- viz výše. if Z > W: # pow je jméno 'zabudované' funkce. print pow(Z, W) return Z else: return Y # Lokální Y neexistuje, takže se použije globální.
Pokud importujeme modul, jako je například sys, stane se
jméno sys lokáln> dostupným jménem. Poté můžeme jména uvnitř
prostoru jmen modulu sys zpřístupnit použitím takzvaného
kvalifikovaného jména, jak jsme si ukázali dříve. (Kvalifikované jméno se od
holého liší tím, že holému jménu předřadíme takzvaný kvalifikátor, který má
podobu dalšího jména, vhodn> spojeného s původním holým jménem. V
jazyce Python se ob> části odd>lují tečkou. Například v jazyce C++ se
odd>lují dv>ma dvojtečkami.)
Pokud napíšeme
from sys import exit
pak v lokálním prostoru jmen zpřístupníme pouze funkci exit.
Nemůžeme použít žádné jiné jméno z modulu sys a dokonce ani
samotné jméno modulu sys.
BASIC volí ve srovnání z jazykem Python opačný přístup. Všechny vytvořené
prom>nné se automaticky stávají globálními (aby byla zachována
kompatibilita, tedy
slučitelnost, s programy psanými pro starší verze jazyka BASIC), ale
programátor může vytvářet i prom>nné, které jsou lokální uvnitř funkcí, jejich označením klíčovým
slovem — LOCAL.
Asi si mohu dovolit tvrdit, že v Tcl neexistuje žádný mechanismus pro přístup k různým úrovním viditelnosti jmen. Důvodem je asi zvláštní způsob, jakým Tcl program provádí. Všechny prom>nné se v každém případ> jeví jako lokální vzhledem k jejich nejbližšímu okolí — prom>nné na úrovni souboru jsou viditelné pouze pro příkazy uvnitř stejného souboru a prom>nné procedur jsou viditelné pouze uvnitř procedur. Komunikaci mezi t>mito prostory jmen můžeme zajistit pouze předáváním hodnot v podob> parametrů, při volání zmín>ných procedur.
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: cztutname.html,v 1.6 2005/09/15 18:24:08 petr Exp $