En cas de doute, laissez-le "public" - je veux dire, n'ajoutez rien pour masquer le nom de votre attribut. Si vous avez une classe avec une valeur interne, ne vous inquiétez pas. Au lieu d'écrire:
class Stack(object):
def __init__(self):
self.__storage = [] # Too uptight
def push(self, value):
self.__storage.append(value)
écrivez ceci par défaut:
class Stack(object):
def __init__(self):
self.storage = [] # No mangling
def push(self, value):
self.storage.append(value)
C'est à coup sûr une manière controversée de faire les choses. Les débutants en Python le détestent et même certains vieux gars de Python méprisent cette valeur par défaut - mais c'est quand même la valeur par défaut, donc je vous recommande vraiment de la suivre, même si vous vous sentez mal à l'aise.
Si vous voulez vraiment envoyer le message "Je ne peux pas y toucher!" pour vos utilisateurs, la méthode habituelle consiste à faire précéder la variable d' un trait de soulignement. Ce n'est qu'une convention, mais les gens la comprennent et font double attention lorsqu'ils traitent de telles choses:
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)
Cela peut également être utile pour éviter les conflits entre les noms de propriétés et les noms d'attributs:
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'en est-il du double trait de soulignement? Eh bien, la magie du double trait de soulignement est principalement utilisée pour éviter la surcharge accidentelle des méthodes et les conflits de noms avec les attributs des superclasses . Cela peut être très utile si vous écrivez une classe qui devrait être étendue plusieurs fois.
Si vous souhaitez l'utiliser à d'autres fins, vous pouvez, mais ce n'est ni habituel ni recommandé.
EDIT : Pourquoi est-ce ainsi? Eh bien, le style Python habituel ne met pas l'accent sur le fait de rendre les choses privées - au contraire! Il y a de nombreuses raisons à cela - la plupart sont controversées ... Voyons quelques-unes d'entre elles.
Python a des propriétés
La plupart des langages OO utilisent aujourd'hui l'approche opposée: ce qui ne doit pas être utilisé ne doit pas être visible, les attributs doivent donc être privés. Théoriquement, cela donnerait des classes plus faciles à gérer et moins couplées, car personne ne changerait imprudemment les valeurs à l'intérieur des objets.
Cependant, ce n'est pas si simple. Par exemple, les classes Java ont de nombreux attributs et getters qui n'obtiennent que les valeurs et les setters qui ne font que définir les valeurs. Vous avez besoin, disons, de sept lignes de code pour déclarer un seul attribut - qui, selon un programmeur Python, est inutilement complexe. De plus, en pratique, vous écrivez simplement tout ce code pour obtenir un champ public, car vous pouvez modifier sa valeur en utilisant les getters et les setters.
Alors, pourquoi suivre cette politique privée par défaut? Rendez simplement vos attributs publics par défaut. Bien sûr, cela pose un problème en Java, car si vous décidez d'ajouter une validation à votre attribut, il vous faudrait tout changer
person.age = age;
dans votre code pour, disons,
person.setAge(age);
setAge()
étant:
public void setAge(int age) {
if (age >= 0) {
this.age = age;
} else {
this.age = 0;
}
}
Donc en Java (et dans d'autres langages), la valeur par défaut est d'utiliser les getters et les setters de toute façon, car ils peuvent être ennuyeux à écrire mais peuvent vous faire gagner beaucoup de temps si vous vous trouvez dans la situation que j'ai décrite.
Cependant, vous n'avez pas besoin de le faire en Python, car Python a des propriétés. Si vous avez ce cours:
class Person(object):
def __init__(self, name, age):
self.name = name
self.age = age
et puis vous décidez de valider les âges, vous n'avez pas besoin de changer les person.age = age
morceaux de votre code. Ajoutez simplement une propriété (comme indiqué ci-dessous)
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 vous pouvez le faire et continuer à l'utiliser person.age = age
, pourquoi ajouteriez-vous des champs privés, des getters et des setters?
(En outre, voir Python n'est pas Java et cet article sur les inconvénients liés à l'utilisation des getters et des setters .).
Tout est visible de toute façon - et essayer de se cacher complique simplement votre travail
Même dans les langues où il existe des attributs privés, vous pouvez y accéder via une sorte de bibliothèque de réflexion / introspection. Et les gens le font beaucoup, dans des cadres et pour résoudre des besoins urgents. Le problème est que les bibliothèques d'introspection ne sont qu'un moyen difficile de faire ce que vous pourriez faire avec les attributs publics.
Puisque Python est un langage très dynamique, il est tout simplement contre-productif d'ajouter ce fardeau à vos classes.
Le problème n'est pas possible de voir - il est nécessaire de voir
Pour un Pythonista, l'encapsulation n'est pas l'incapacité de voir les internes des classes, mais la possibilité d'éviter de la regarder. Ce que je veux dire, c'est que l'encapsulation est la propriété d'un composant qui lui permet d'être utilisé sans que l'utilisateur se soucie des détails internes. Si vous pouvez utiliser un composant sans vous soucier de son implémentation, alors il est encapsulé (de l'avis d'un programmeur Python).
Maintenant, si vous avez écrit votre classe de telle manière que vous pouvez l'utiliser sans avoir à penser aux détails d'implémentation, il n'y a aucun problème si vous voulez regarder à l'intérieur de la classe pour une raison quelconque. Le fait est que votre API doit être bonne et le reste, ce sont les détails.
Guido l'a dit
Eh bien, ce n'est pas controversé: il l'a dit, en fait . (Cherchez «kimono ouvert».)
C'est la culture
Oui, il y a quelques raisons, mais aucune raison critique. Il s'agit principalement d'un aspect culturel de la programmation en Python. Franchement, cela pourrait aussi être l'inverse - mais ce n'est pas le cas. De plus, vous pourriez tout aussi facilement demander l'inverse: pourquoi certaines langues utilisent-elles des attributs privés par défaut? Pour la même raison principale que pour la pratique Python: parce que c'est la culture de ces langages, et chaque choix a des avantages et des inconvénients.
Puisqu'il existe déjà cette culture, il est conseillé de la suivre. Sinon, vous serez ennuyé par les programmeurs Python vous disant de supprimer le __
de votre code lorsque vous posez une question dans Stack Overflow :)