TI/Programowanie z Pythonem/Programowanie zorientowane obiektowo/Zmienne prywatne

Z Brain-wiki

W Pythonie są trzy różne kategorie nazw zaczynających się od podkreślenia, ale tak naprawdę nie mają one ze sobą dużo wspólnego. Najważniejsze są funkcje wywoływane automatycznie opisanej [[../#Specjalne metody w Pythonie|gdzie indziej]], które mają po parze podkreśleń na początku i na końcu. Oprócz tego występują zmienne prywatne, zaczynające się od jednego lub dwóch podkreśleń. Takie zmienne nie są przeznaczone do tego, by się do nich odwoływać z spoza klasy czy modułu.

W szczególności przy wywołaniu from ... import *, czyli imporcie wszystkiego naraz, domyślnie dostajemy tylko nazwy niezaczynające się od podkreślenia.

Rozróżnenie pomiędzy zmiennymi publicznymi i prywatnymi ma znaczenie w przypadku modułów bibliotecznych — czyli takich które pełnią rolę służebną wobec innych modułów dostarczając im metody do wywołania. Programy definiowane przez użytkownika też składają się z modułów, ale to jak zostaną nazwane zmienne i funkcji oraz jakim będą ulegać zmianom wraz z rozwojem programu, jest tak naprawdę istotne tylko dla autorów tego programu. Poniższe rozważania dotyczą więc modułów przeznaczonych do wykorzystania przez innych, czyli w szczególności modułów w standardowej bibliotece Pythona.

Nazwy niepoprzedzone podkreśleniem są elementem "interfejsu", czyli mogą być wykorzystywane przez inne moduły i nie powinny ulegać zmianie wraz z rozwojem modułu w którym są zadeklarowane. Rozpoczęcie nazwy od pojedynczego podkreślenia oznacza, że ta zmienna jest elementem implementacji, który może ulec zmianie. Nie oznacza to, że do takiej zmiennej uniemożliwiony jest dostęp, ani nawet że nie należy się do niej odwoływać. Pojedyncze podkreślenie ostrzega tylko użytkownia przed tym, że dostęp do niej następuje na jego ryzyko.

Nazwy poprzedzone podwójnym podkreśleniem zachowują się w sposób szczególny. W trakcie wykonywania definicji (czyli przy czytaniu programu), interpreter zamienia podwójne podkreślenie na specjalny prefiks zależny od nazwy klasy czy modułu w którym następuje definicja. Np. jesli zadeklarujemy pole __a w klasie A, to zostanie utworzone pole o nazwie _A__a, poprzez połączenie nazwy klasy i pola. Celem tego podstawienia jest to, by klasa dziedzicząca mogła swobodnie zdefiniować pole o takiej samej nazwie.

>>> class A(object):
...     __v = 1
...     def a(self):
...          return self.__v
>>> class B(A):
...     __v = 2
...     def b(self):
...          return self.__v
>>> a = A()
>>> print a.a()
1
>>> b = B()
>>> print b.b()
2
>>> print b.a() # !
1
>>> b._B__v, b._A__v
(2, 1)

Widzimy, że mamy pole o pozornie takiej samej nazwie (__v), wykorzystywane przez A.a i B.b, bez konfliktu. Oczywiście tak jak pokazuje ostatnia linijka, dostęp do pól "prywatnych" nie jest szczególnie trudny, nawet spoza danej klasy.

Ponieważ wykorzystanie zmiennych prywatnych (z _ i __), nie jest w żaden sposób utrudnione, można by się zapytać, jaki jest ich sens? Okazuje się, że te pierwsze (z pojedynczym podkreśleniem) mają sens, bo mówią o intencjach, natomiast te drugie są raczej ukłonem w stronę programistów przyzwyczajonych do innych języków programowania i wielekiego sensu w Pythonie nie mają. Żartobliwe motto strzeszczające dostęp do zmiennych "prywantych" w Pythonie brzmi "we are all consenting adults here". Ta fraza jest takim elementem Pythonowego folkloru, ale symbolizuje zdecydowanie poważną filozofię. Skoro programista może użyć dostępnych funkcji w niewłaściwy sposób i napisać niepoprawny program na tysiąc sposobów, skoro można nawet zmienić kod innych klas w trakcie działania programu, to wymuszanie reguł dostępu do niektórych pól przez interpreter byłoby tylko stratą czasu. Oczywiście zawsze należy chronić się przez pomyłkami, więc zmienne "prywatne" są w czytelny sposób oznaczone podkreśleniem — i kiedy się ich używa z zewnątrz, to jest to dozwolone, ale tylko na własną odpowiedzialność. Ogólna zasada jest taka, że zmienne prywatne zdefiniowane w obiektach bibliotecznych mogą się zmienić z wersji na wersję, wedle widzimisię autorów tych bibliotek. Natomiast w przypadku zmiennych publicznych, a zwłaszcza udokumentowanych zmiennych publicznych, możemy oczekiwać, że nie ulegną one niekompatybilnej zmianie w nowszych wersjach bez istotnego powodu. Zmienne podwójnie prywatne (z "__") są natomiast używane znacznie rzadziej.