Historia del tema
En la programación orientada a objetos clásica, la encapsulación se implementa mediante la limitación del acceso a los datos internos. La mayoría de los lenguajes tienen modificadores de acceso estrictos. En Python, se aplica el principio de "todos somos adultos" — no hay una privacidad estricta.
Problema
Los desarrolladores confunden los atributos y métodos protegidos (_protected) y privados (__private) en Python, creyendo que el "doble guión bajo" proporciona una protección completa, o asumiendo que no hay protección alguna.
Solución
Python implementa convenciones: un solo guión bajo _var — protegido, doble __var — privado (el nombre se transforma mediante mangling). El acceso a tal atributo o método es posible, pero más difícil: se llama _ClassName__var.
Ejemplo de código:
class Example: def __init__(self): self._protected = 1 # protegido self.__private = 2 # privado (name mangling) ex = Example() print(ex._protected) # 1 #print(ex.__private) # AttributeError print(ex._Example__private) # 2 (name mangling)
Características clave:
¿Se puede acceder a un campo "privado" con doble guión bajo a través de una instancia?
Sí, a través del mangling: _ClassName__var. Así que los datos son accesibles, simplemente de manera implícita.
¿Cómo se comportará un método/atributo privado en la herencia?
El name mangling evita que los descendientes sobreescriban accidentalmente los elementos privados del padre, pero se puede acceder a ellos mediante _ParentClass__attr. Los métodos con doble guión bajo no son "visibles" desde fuera de la clase hija.
class A: def __foo(self): print("A") class B(A): def bar(self): # self.__foo() — error self._A__foo() # funciona
¿Hay privacidad total en Python como en JVM/C++?
No. Todo se basa en convenciones y mangling. No se puede proteger completamente los datos, ya que Python permite dinámicamente acceder a cualquier atributo.
En una gran biblioteca, un usuario intentó cambiar un atributo privado a través de un doble guión bajo, pensando que era un "secreto" — pero mediante _ClassName__var el cambio ocurrió de todas formas.
Pros:
Contras:
En el proyecto se acordó usar un solo guión bajo para los campos internos y no tocarlos fuera de la clase. Se agregó una propiedad para acceso seguro.
Pros:
Contras: