SAMOUCZEK JĘZYKA PYTHON ROZDZIAŁY   
Rozdział 8: Klasy

1: Terminologia- 2: Przestrzenie i zasięgi nazw w Pythonie- 3: Składnia definicji klasy - 4: Obiekty klasy
5: Obiekty konkretu klasy- 6: Obiekty metod- 7: Luźne uwagi - 8: Dziedziczenie- 9: Dziedziczenie wielorakie
10: Zmienne prywatne- 11: Sztuczki i chwyty - 12: Wjątki mogą być klasami

Lekcja 2: Przestrzenie i zasięgi nazw w Pythonie


Zanim przejdziemy do omawiania klas, należy wspomnieć o regułach zasięgu nazw w Pythonie. Definicja klasy wprowadza do koncepcji przestrzeni nazw trochę zamieszania i powinno się wiedzieć jak działają zasięgi przestrzeni nazw, aby w pełni zrozumieć, co się w klasach dzieje. Wiedza o tym mechanizmie jest bardzo użyteczna dla każdego zaawansowanego programisty Pythona.

Zacznijmy od definicji.
Przestrzeń nazw jest wskazaniem obiektu poprzez nazwę. Większość przestrzeni nazw w Pythonie zaimplementowanych jest obecnie w postaci pythonowych słowników, ale zwykle nie jest to zauważalne (z wyjątkiem wydajności) i może się w przyszłości zmienić. Przykładami przestrzeni nazw są: zbiór nazw wbudowanych (funkcje takie jak abs() i nazwy wyjątków wbudowanych), nazwy globalne modułu i nazwy lokalne podczas wywołania funkcji. W pewnym sensie, zbiór atrybutów obiektów także jest przestrzenią nazw. Ważne jest, aby pamiętać, że nie istnieje absolutnie żaden związek pomiędzy nazwami z różnych przestrzeni nazw. Dwa różne moduły mogą definiować funkcję "maksymalizuj" - użytkownik tych modułów musi poprzedzić jej nazwę nazwą modułu.

Używamy słowa atrybut dla każdej nazwy poprzedzonej kropką - np. w wyrażeniu z.real, real jest atrybutem obiektu z. Mówiąc ściśle, odniesienia do nazw w modułach są odniesieniami do atrybutów: w wyrażeniu nazwa_modulu.nazwa_funkcji, nazwa_modulu jest obiektem modułu, a nazwa_funkcji jest jego atrybutem. W tym przypadku istnieje bezpośrednia relacja pomiędzy atrybutami modułu i nazwami globalnymi w nim zdefiniowanymi: oba rodzaje nazw zdefiniowane są w tej samej przestrzeni nazw! ( Z wyjątkiem jednej rzeczy. Obiekty modułów posiadają tajemniczy tylko atrybut do odczytu: __dict__, któremu przypisany jest słownik użyty do zaimplementowania przestrzeni nazw. Nazwa __dict__ jest atrybutem, ale nie nazwą globalną. To oczywiste, że używanie tej nazwy jest pogwałceniem zasad implementacji przestrzeni nazw i powinno być ograniczone tylko do przypadków śledzenia programu typu "post-mortem")

Atrybuty mogą być tylko do odczytu lub zapisywalne. W tym ostatnim przypadku można dokonać operacji przypisania wartości do atrybutu. Atrybuty modułu są zapisywalne: można np. napisać "modul.wynik = 42". Tego rodzaju atrybuty mogą być usuwane za pomocą operatora del, np. "del modul.wynik".

Przestrzenie nazw tworzone są w różnych chwilach i są aktywne przez różny czas. Przestrzeń nazw zawierająca nazwy wbudowane tworzona jest podczas rozpoczęcia pracy Pythona i nigdy nie jest usuwana. Przestrzeń nazw globalnych modułu tworzona jest podczas wczytywania jego definicji i jest aktywna również do chwili zakończenia pracy interpretera. Instrukcje wykonywane przez szczytowe wywołania interpretera, zarówno czytane z pliku jak i wprowadzane interaktywnie, są częścią modułu o nazwie __main__ - tak więc posiadają swoją własną przestrzeń nazw globalnych. (Nazwy wbudowane również przechowywane są w module o nazwie __builtin__.)

Przestrzeń nazw lokalnych funkcji tworzona jest w momencie jej wywołania i niszczona, gdy następuje powrót z funkcji lub zgłoszono został w niej wyjątek, który nie został tam obsłużony ("zapomniany" byłoby właściwym słowem, które dokładnie oddałoby to, co naprawdę się wtedy dzieje). Oczywiście, wywołanie rekurencyjne powoduje tworzenie za każdym razem nowej przestrzeni nazw lokalnych.

Zasięg jest tekstowym obszarem programu Pythona, w którym przestrzeń nazw jest wprost osiągalna. "Wprost osiągalna" oznacza tutaj, że niekwalifikowane (nie trzeba podawać nazwy modułu, klasy, obiektu wraz z kropką) odniesienia do nazwy znajdują tę nazwę w obowiązującej przestrzeni nazw.

Pomimo iż zasięgi określane są w sposób statyczny, używane są w sposób dynamiczny. W każdym momencie wykonania programu, używa się dokładnie trzech zagnieżdżonych zasięgów nazw (tzn. wprost osiągalne są trzy przestrzenie nazw):

  • najbardziej zagnieżdżony, w którym najpierw poszukuje się nazwy, zawiera on nazwy lokalne;
  • środkowy, przeszukiwany w następnej kolejności, który zawiera aktualne nazwy globalne modułu;
  • zewnętrzny (przeszukiwany na końcu) jest zasięgiem nazw wbudowanych.
Lokalny zasięg nazw umożliwia zwykle odniesienia do nazw występujących (tekstowo) w bieżącej funkcji. Poza obrębem funkcji, lokalna nazwa jest nazwą z przestrzeni nazw globalnych modułu. Definicja klasy stanowi jeszcze jedną przestrzeń nazw w rodzinie przestrzeni nazw lokalnych.

Ważne jest zdawać sobie sprawę z tego, że zasięgi nazw określane są statycznie: zasięg globalny funkcji zdefiniowanej w module jest jego przestrzenią nazw globalnych, bez względu na to skąd i za pomocą jakiego aliasu funkcja została wywołana. Z drugiej strony, właściwe poszukiwanie nazw zachodzi w sposób dynamiczny, w czasie wykonywania programu - jakkolwiek, definicja języka ewoluuje w stronę statycznego sposobu rozstrzygania nazw, w czasie kompilacji. Nie można więc polegać w programach na dynamicznym rozstrzyganiu nazw (w rzeczywistości, zmienne lokalne są już w obecnej wersji określane statycznie).

Jedną z cech szczególnych Pythona jest to, że przypisanie zawsze zachodzi w najbardziej zagnieżdżonym zasięgu. Przypisania nie powodują kopiowania danych - przywiązują jedynie nazwy do obiektów. To samo zachodzi w przypadku usuwania: instrukcja " del x" usuwa związek obiektu identyfikowanego przez nazwę x z ta nazwą w przestrzeni nazw lokalnych. W rzeczywistości, wszystkie operacje, które wprowadzają nowe nazwy do przestrzeni nazw lokalnych, to robią. Dotyczy to zawłaszcza instrukcji importu i definicji funkcji (instrukcja global może zostać użyta do oznaczenia, że wyszczególniona nazwa należy do przestrzeni nazw globalnych).
Strona główna - O Pythonie - Interpreter - Samouczek - Przykłady programów - Linki