En caso de duda, déjelo en "público", es decir, no agregue nada para ocultar el nombre de su atributo. Si tienes una clase con algún valor interno, no te preocupes por eso. En lugar de escribir:
class Stack(object):
def __init__(self):
self.__storage = [] # Too uptight
def push(self, value):
self.__storage.append(value)
escribe esto por defecto:
class Stack(object):
def __init__(self):
self.storage = [] # No mangling
def push(self, value):
self.storage.append(value)
Esta es sin duda una forma controvertida de hacer las cosas. Los novatos de Python simplemente lo odian e incluso algunos viejos de Python desprecian este valor predeterminado, pero de todos modos es el predeterminado, por lo que realmente te recomiendo que lo sigas, incluso si te sientes incómodo.
Si realmente desea enviar el mensaje "¡No puedo tocar esto!" para sus usuarios, la forma habitual es anteponer la variable con un guión bajo. Esto es solo una convención, pero la gente lo entiende y tiene doble cuidado al tratar con tales cosas:
class Stack(object):
def __init__(self):
self._storage = [] # This is ok but pythonistas use it to be relaxed about it
def push(self, value):
self._storage.append(value)
Esto también puede ser útil para evitar conflictos entre nombres de propiedades y nombres de atributos:
class Person(object):
def __init__(self, name, age):
self.name = name
self._age = age if age >= 0 else 0
@property
def age(self):
return self._age
@age.setter
def age(self, age):
if age >= 0:
self._age = age
else:
self._age = 0
¿Qué pasa con el doble subrayado? Bueno, la magia de doble subrayado se usa principalmente para evitar la sobrecarga accidental de métodos y conflictos de nombres con los atributos de las superclases. . Puede ser muy útil si escribe una clase que se espera que se amplíe muchas veces.
Si desea utilizarlo para otros fines, puede hacerlo, pero no es ni habitual ni recomendable.
EDITAR : ¿Por qué es así? Bueno, el estilo habitual de Python no enfatiza que las cosas sean privadas, ¡al contrario! Hay muchas razones para eso, la mayoría de ellas controvertidas ... Veamos algunas de ellas.
Python tiene propiedades
La mayoría de los lenguajes orientados a objetos en la actualidad utilizan el enfoque opuesto: lo que no debe usarse no debe ser visible, por lo que los atributos deben ser privados. Teóricamente, esto produciría clases más manejables y menos acopladas, porque nadie cambiaría los valores dentro de los objetos de forma imprudente.
Sin embargo, no es tan sencillo. Por ejemplo, las clases de Java tienen muchos atributos y captadores que solo obtienen los valores y establecedores que solo establecen los valores. Necesita, digamos, siete líneas de código para declarar un solo atributo, lo que un programador de Python diría que es innecesariamente complejo. Además, en la práctica, simplemente escribe todo este código para obtener un campo público, ya que puedes cambiar su valor usando los getters y setters.
Entonces, ¿por qué seguir esta política de privacidad predeterminada? Simplemente haga públicos sus atributos de forma predeterminada. Por supuesto, esto es problemático en Java, porque si decide agregar alguna validación a su atributo, sería necesario que cambie todos
person.age = age;
en su código para, digamos,
person.setAge(age);
setAge()
siendo:
public void setAge(int age) {
if (age >= 0) {
this.age = age;
} else {
this.age = 0;
}
}
Entonces, en Java (y otros lenguajes), el valor predeterminado es usar getters y setters de todos modos, porque pueden ser molestos de escribir pero pueden ahorrarle mucho tiempo si se encuentra en la situación que he descrito.
Sin embargo, no es necesario que lo haga en Python, ya que Python tiene propiedades. Si tienes esta clase:
class Person(object):
def __init__(self, name, age):
self.name = name
self.age = age
y luego decides validar las edades, no necesitas cambiar las person.age = age
partes de tu código. Simplemente agregue una propiedad (como se muestra a continuación)
class Person(object):
def __init__(self, name, age):
self.name = name
self._age = age if age >= 0 else 0
@property
def age(self):
return self._age
@age.setter
def age(self, age):
if age >= 0:
self._age = age
else:
self._age = 0
Si puede hacerlo y seguir utilizándolo person.age = age
, ¿por qué agregaría campos privados y captadores y definidores?
(Además, consulte Python no es Java y este artículo sobre los daños de usar getters y setters ).
Todo es visible de todos modos, y tratar de esconderse solo complica su trabajo
Incluso en idiomas donde hay atributos privados, puede acceder a ellos a través de algún tipo de biblioteca de reflexión / introspección. Y la gente lo hace mucho, en marcos y para resolver necesidades urgentes. El problema es que las bibliotecas de introspección son solo una forma difícil de hacer lo que podría hacer con los atributos públicos.
Dado que Python es un lenguaje muy dinámico, es contraproducente agregar esta carga a sus clases.
El problema es que no se puede ver, se requiere ver
Para un Pythonista, la encapsulación no es la incapacidad de ver el interior de las clases, sino la posibilidad de evitar mirarlo. Lo que quiero decir es que la encapsulación es la propiedad de un componente que permite su uso sin que el usuario se preocupe por los detalles internos. Si puede usar un componente sin preocuparse por su implementación, entonces está encapsulado (en opinión de un programador de Python).
Ahora, si escribió su clase de tal manera que pueda usarla sin tener que pensar en los detalles de implementación, no hay problema si lo desea. mirar dentro de la clase por alguna razón. El punto es: tu API debería ser buena y el resto son detalles.
Guido lo dijo
Bueno, esto no es controvertido: lo dijo, en realidad . (Busque "kimono abierto").
Esta es la cultura
Sí, hay algunas razones, pero ninguna razón crítica. Este es principalmente un aspecto cultural de la programación en Python. Francamente, también podría ser al revés, pero no es así. Además, podría preguntar fácilmente al revés: ¿por qué algunos lenguajes usan atributos privados de forma predeterminada? Por la misma razón principal que para la práctica de Python: porque es la cultura de estos lenguajes, y cada elección tiene ventajas y desventajas.
Dado que ya existe esta cultura, se recomienda seguirla. De lo contrario, los programadores de Python le molestarán y le pedirán que elimine el__
de su código cuando haga una pregunta en Stack Overflow :)