Další Předchozí Obsah

11. Jmenné prostory

11.1 Myšlenky, reference counting

Je-li Python spuštěn v neinteraktivním režimu, zkompiluje vstupní soubor do bytekódu a začne jej řádek po řádku provádět. Když narazí na definici proměnné, vytvoří někde v paměti objekt příslušného typu (číslo, slovník, seznam či jiný) a poznamená si, že toto jméno odpovídá tomuto objektu v paměti. Narazí-li na definici funkce, vytvoří objekt typu funkce, uloží jej někde do paměti a opět si poznamená, že toto jméno odpovídá tomuto objektu.

Místo, kam se poznamenává vazba jména a objektu se nazývá jmenný prostor (v anglické terminologii namespace). Každé přiřazení či definice vytváří položku ve jmenném prostoru. Příkazem del se položka ze jmenného prostoru ruší. Zároveň každý objekt nese informaci o tom, kolikrát je použit. V okamžiku, kdy je zrušen poslední odkaz na objekt, je z paměti uvolněn i příslušný objekt.

Počet odkazů na objekt je možné zjistit pomocí funkce ref(), jednoznačný identifikátor objektu je možné zjistit pomocí funkce id().

Uvažujme následující kousek programu

>>> r = [ 1, 2, 3, 4, 5 ]
>>> s = [ 1, 2, 3, 4, 5 ]
>>> t = r

Seznamy nazvané r a s jsou dva různé objekty, jména r a t jsou dvě různá jména pro tentýž objekt. Proto se jakákoliv změna v seznamu t projeví i v seznamu r.

>>> r.append(':-)')
>>> s
[1, 2, 3, 4, 5]
>>> t
[1, 2, 3, 4, 5, ':-)']

Je dokonce možné vytvářet rekurzivní objekty:

>>> r = range(5)
>>> r.append(r)

Posledním prvkem seznamu r je teď seznam r. Takovéto věci je ale vhodné dělat až v okamžiku, kdy přesně víme, co děláme. Při hodně nešikovném používání je možné zacyklit datové struktury tak, že počítání odkazů přestane fungovat a v paměti mohou zůstávat obsazené nepoužívané bloky.

OTOH: V okamžiku, kdy člověk začne potřebovat rekurzivní datové struktury, už většinou přesně ví, co dělá.

11.2 Globální a lokální jmenný prostor

Každý soubor má vlastní globální jmenný prostor. Patří do něho všechny objekty, které byly vytvořeny na nejvyšší úrovni. (Na nejvyšší úrovni nemyslím na úrovni vlády, ale bez jakéhokoliv odsazeni :-). Kromě toho při vstupu do libovolné funkce se vytváří lokální jmenný prostor.

Na nejvyšší úrovni se pro zápis i pro čtení používá zapisuje do globálního jmenného prostoru. Příkazy, které se provádí z promptu jsou prováděny v globálním jmenném prostoru. Při volání funkce se vytváří lokální jmenný prostor. Všechny nově vytvářené objekty se vytváří v lokálním jmenném prostoru. Při hledání objektu se nejprve projde lokální jmenný prostor a až poté globální jmenný prostor.

>>> l = [ 'globalni' ]     
>>> def f():
...     l = ['lokalni']
... 
>>> f()
>>> l
['globalni']

Ale pozor, pokud jsou objekty modifikovány, modifikace se provádí tam, kde jsou objekty definovány.

>>> l = [ 'globalni' ]     
>>> def f():
...     l.append('lokalni')
... 
>>> f()
>>> l
['globalni', 'lokalni']

Je-li ve funkci potřeba modifikovat globální prostor jmen, je možné použít direktivu global se jmény objektů, které budou přiřazeny do globálního jmenného prostoru.

>>> def f():
...     global s
...     s = 'lokalne zapsano'
... 
>>> f()
>>> s
'lokalne zapsano'


Další Předchozí Obsah