Storia della questione
Nella programmazione orientata agli oggetti classica, l'incapsulamento si realizza tramite la limitazione dell'accesso ai dati interni. La maggior parte dei linguaggi ha modificatori di accesso rigorosi. In Python vige il principio "siamo tutti adulti" — non esiste una rigorosa privacy.
Problema
Gli sviluppatori confondono gli attributi e i metodi protetti (_protected) e privati (__private) in Python, pensando che "il doppio underscore" garantisca una protezione completa, oppure credono che non ci sia affatto protezione.
Soluzione
Python implementa delle convenzioni: il singolo underscore _var è protetto, il doppio __var è privato (il nome subisce mangling). L'accesso a tale attributo o metodo è possibile, ma più difficile: si chiama _ClassName__var.
Esempio di codice:
class Example: def __init__(self): self._protected = 1 # protetto self.__private = 2 # privato (name mangling) ex = Example() print(ex._protected) # 1 #print(ex.__private) # AttributeError print(ex._Example__private) # 2 (name mangling)
Caratteristiche chiave:
È possibile accedere a un campo "privato" con doppio underscore attraverso un'istanza?
Sì, tramite mangling: _ClassName__var. Quindi i dati sono accessibili, solo implicitamente.
Come si comporta un metodo/attributo privato durante l'ereditarietà?
Il name mangling impedisce ai discendenti di sovrascrivere accidentalmente gli elementi privati del genitore, ma è possibile accedere tramite _ParentClass__attr. I metodi con doppio underscore non sono "visibili" al di fuori della classe discendente.
class A: def __foo(self): print("A") class B(A): def bar(self): # self.__foo() — errore self._A__foo() # funziona
C'è una completa privacy in Python come in JVM/C++?
No. Tutto si basa su convenzioni e mangling. Non è possibile proteggere completamente i dati, poiché Python consente dinamicamente di accedere a qualsiasi attributo.
In una grande libreria, un utente ha tentato di modificare un attributo privato tramite doppio underscore, pensando che fosse un "segreto" — ma tramite _ClassName__var la modifica è comunque avvenuta.
Pro:
Contro:
Nel progetto si sono accordati di utilizzare un singolo underscore per i campi interni e di non toccarli al di fuori della classe. È stata aggiunta una property per un accesso sicuro.
Pro:
Contro: