Historia pytania
W klasycznym programowaniu obiektowym inkapsulacja realizowana jest poprzez ograniczenie dostępu do danych wewnętrznych. W większości języków istnieją ścisłe modyfikatory dostępu. W Pythonie obowiązuje zasada "wszyscy jesteśmy dorosłymi ludźmi" — nie ma ścisłej prywatności.
Problem
Programiści mylą chronione (_protected) i prywatne (__private) atrybuty oraz metody w Pythonie, uważając, że "podwójne podkreślenie" zapewnia pełną ochronę, lub sądzą, że ochrona nie istnieje wcale.
Rozwiązanie
Python realizuje konwencje: pojedyncze podkreślenie _var — chronione, podwójne __var — prywatne (nazwa podlega mangle’owaniu). Dostęp do takiego atrybutu lub metody jest możliwy, ale trudniejszy: nazywa się _ClassName__var.
Przykład kodu:
class Example: def __init__(self): self._protected = 1 # chronione self.__private = 2 # prywatne (name mangling) ex = Example() print(ex._protected) # 1 #print(ex.__private) # AttributeError print(ex._Example__private) # 2 (name mangling)
Kluczowe cechy:
Czy można uzyskać dostęp do "prywatnego" pola z podwójnym podkreśleniem przez instancję?
Tak, poprzez mangle’owanie: _ClassName__var. Tak więc dane są dostępne, tylko niejawnie.
Jak zachowa się prywatna metoda/atrybut przy dziedziczeniu?
Name mangling utrudnia potomkom przypadkowe nadpisanie prywatnych elementów rodzica, ale dostęp można uzyskać przez _ParentClass__attr. Metody z podwójnym podkreśleniem nie są "widoczne" z zewnątrz klasy-dziedzica.
class A: def __foo(self): print("A") class B(A): def bar(self): # self.__foo() — błąd self._A__foo() # działa
Czy w Pythonie istnieje pełna prywatność na poziomie JVM/C++?
Nie. Wszystko opiera się na konwencjach i mangle’owaniu. Całkowita ochrona danych nie jest możliwa, ponieważ Python dynamicznie pozwala na dostęp do dowolnych atrybutów.
W dużej bibliotece użytkownik próbował zmienić prywatny atrybut przez podwójne podkreślenie, myśląc, że to "tajemnica" — ale przez _ClassName__var zmiana i tak miała miejsce.
Zalety:
Wady:
W projekcie uzgodniono stosowanie pojedynczego podkreślenia dla wewnętrznych pól i nie dotykanie ich poza klasą. Dodano property dla bezpiecznego dostępu.
Zalety:
Wady: