En cas de doute, laisser "public" - je veux dire, ne pas ajouter quoi que ce soit pour cacher le nom de l'attribut. Si vous avez une classe à l'interne de la valeur, ne vous inquiétez pas à ce sujet. Au lieu d'écrire:
class Stack(object):
def __init__(self):
self.__storage = [] # Too uptight
def push(self, value):
self.__storage.append(value)
écrire ce par défaut:
class Stack(object):
def __init__(self):
self.storage = [] # No mangling
def push(self, value):
self.storage.append(value)
C'est sûr controversée sur la façon de faire les choses. Python débutants il suffit de la haine et même certains vieux Python gars mépriser ce défaut - mais c'est le défaut de toute façon, donc je vous recommande vraiment de vous suivre, même si vous vous sentez mal à l'aise.
Si vous vraiment voulez envoyer le message à vos utilisateurs en disant "ne Peut pas toucher cela!", la méthode habituelle consiste à faire précéder la variable avec un trait de soulignement. C'est juste une convention, mais les gens à comprendre et à prendre le double de soins face à de telles choses:
class Stack(object):
def __init__(self):
self._storage = [] # This is ok but pythonistas use to be relaxed about it
def push(self, value):
self._storage.append(value)
Cela peut être utile, aussi, pour éviter les conflits entre noms de propriétés et les noms d'attribut:
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
Quel est le trait de soulignement double? Eh bien, il semble que le trait de soulignement double magie est utilisée principalement pour éviter les blessures accidentelles surcharge de méthodes. Si vous souhaitez utiliser par la suite, vous pouvez, mais il n'est ni habituel, ni recommandé.
EDIT: Pourquoi est-ce donc? Eh bien, il ya beaucoup de raisons, les plus controversés... Permettez-nous de voir certains d'entre eux.
Python possède des propriétés
La plupart des langages à objets d'aujourd'hui utilisent l'approche inverse: ce qui ne doit pas être utilisé ne doit pas être visible, de sorte que les attributs doit être privé. Théoriquement, cela donnerait plus maniable, moins couplée classes, parce que personne n'aurait de modifier les valeurs à l'intérieur des objets à la légère.
Cependant, ce n'est pas si simple. Par exemple, Java classes ont beaucoup d'attributs et les méthodes de lecture qui vient d'obtenir les valeurs et les setters qui vient de définir les valeurs. Vous avez besoin, disons, sept lignes de code pour déclarer un attribut unique - qui un programmeur Python dirais que c'est inutile complexe. Aussi, dans la pratique, il vous suffit d'écrire ce que beaucoup de code pour obtenir un champ public, puisque vous pouvez changer sa valeur en utilisant les getters et setters.
Alors pourquoi suivre ce privé par défaut de la politique? Juste faire vos attributs sont publics par défaut. Bien sûr, il est problématique en Java, parce que si vous décidez d'ajouter un peu de la validation de votre attribut, elle aurait besoin de vous pour changer tout
person.age = age;
dans votre code, merci de nous le dire,
person.setAge(age);
cours d' setAge()
:
public void setAge(int age) {
if (age >= 0) {
this.age = age;
} else {
this.age = 0;
}
}
Donc en Java (et autres langues) la valeur par défaut est d'utiliser les accesseurs et mutateurs de toute façon, car ils peuvent être gênant pour l'écrire, mais pouvez vous épargner 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, depuis Python ont des propriétés. Si vous aviez cette classe:
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 l' person.age = age
pièces de votre code. Il suffit d'ajouter une propriété (comme illustré 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 à toujours utiliser person.age = age
, pourquoi feriez-vous ajouter des champs privés et des getters et setters?
(Voir aussi Python, Java n'est pas et cet article sur les effets néfastes de l'utilisation des getters et setters.).
Tout est visible de toute façon - et en essayant de cacher juste complique votre travail
Même dans les langues où il y a privé des attributs, vous pouvez y accéder par une sorte de réflexion et d'introspection de la bibliothèque. Et les gens le font un grand nombre de fois, dans des cadres, et pour résoudre les besoins urgents. Le problème est que l'introspection bibliothèques sont juste un moyen dur de faire ce que vous pourriez faire avec le public attributs.
Depuis le Python est très dynamique de la langue, c'est juste contre-productif pour ajouter à ce fardeau à vos classes.
Le problème est de ne pas être possible de voir - est nécessaire pour voir
Pour un Pythonista, l'encapsulation n'est pas l'incapacité de voir les internes des classes, mais la possibilité d'éviter de le regarder. Je veux dire, l'encapsulation est la propriété d'un composant qui permet de l'utiliser sans que l'utilisateur concerné sur les détails internes. Si vous pouvez utiliser un composant sans se soucier de vous-même à propos de sa mise en œuvre, alors il est encapsulé (de l'avis d'un programmeur Python).
Maintenant, si vous avez écrit votre classe de telle sorte que vous pouvez l'utiliser sans avoir à réfléchir sur les détails d'implémentation, il n'y a pas de problème si vous voulez regarder à l'intérieur de la classe pour une raison quelconque. La question est: votre API devrait être bon et le reste est du détail.
Guido dit
Eh bien, ce n'est pas l'objet de controverse: il l'a dit, en fait.
C'est de la culture
Oui, il y a quelques raisons, mais pas de meurtre raison. C'est surtout l'aspect culturel de la programmation en Python. Franchement, il pourrait être dans l'autre sens, trop - mais il ne l'est pas. Aussi, vous pouvez simplement poser dans l'autre sens: pourquoi certaines langues utilisent des attributs par défaut? Pour la même raison principale pour le Python pratique: parce que c'est la culture de ces langues, et chaque choix a ses avantages et ses inconvénients.
Depuis cette culture a grandi, vous êtes bien conseillé de le suivre. Sinon, vous obtiendrez choqué par Python pour les programmeurs en train de vous dire de supprimer l' __
de votre code lorsque vous avez posé une question dans le Débordement de Pile :)
Je sens que ma réponse n'est pas si bon. Désolé, j'ai juste prévu de répondre à la plus simple question à propos de ce qu' est la convention; j'ai juste essayé de répondre au sujet de pourquoi c'est la convention parce que j'ai posté la première réponse. J'espère que cela peut être un peu de clarification, de toute façon.