127 votes

Nom Python Mâlant: En cas de doute, faites quoi?

Dans d'autres langues, une orientation générale qui permet de produire le meilleur code est toujours tout faire comme caché que possible. En cas de doute quant à savoir si une variable doit être privé ou protégé, c'est mieux d'aller avec le privé.

En fait de même vrai pour Python? Dois-je utiliser les deux principaux traits de soulignement sur tout, au premier abord, et seulement rendre moins cachés (un seul trait de soulignement) comme j'ai besoin d'eux?

Edit: Si la convention est d'utiliser un seul trait de soulignement, j'aimerais aussi connaître les raisons.

Edit: Voici un commentaire que j'ai laissé sur JBernardo de réponse. Il explique pourquoi j'ai posé cette question, et aussi pourquoi je voudrais savoir pourquoi Python est différent de toutes les autres langues:

Je viens de langues qui vous entrainer à penser que tout devrait être seulement en tant du public que de besoin et pas plus. Le raisonnement est que cela permettra de réduire les dépendances et rendre le code plus sûr de le modifier. Le Python façon de faire les choses dans l'ordre inverse, à commencer par le secteur public et en allant vers caché -- est étrange pour moi.

212voto

brandizzi Points 11051

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.

16voto

Matt Joiner Points 29194

Je ne dirais pas que la pratique produit un meilleur code. Modificateurs de visibilité seulement vous distraire de la tâche à portée de main, et comme un effet secondaire de la force de votre interface à utiliser comme vous le souhaitez. En règle générale, l'application de visibilité empêche les programmeurs de déconner les choses si ils n'ont pas lu la documentation correctement.

Une bien meilleure solution est la route que Python encourage: Vos classes et les variables doivent être bien documentées, et leur comportement clair. La source doit être disponible. C'est beaucoup plus extensible et fiable pour écrire du code.

Ma stratégie en Python est ceci:

  1. Il suffit d'écrire la fichue chose, ne faire aucune hypothèse sur la façon dont vos données doivent être protégées. Cela suppose que vous écrivez pour créer l'idéal interfaces pour vos problèmes.
  2. Utilisez un trait de soulignement pour les choses qui probablement ne sera pas utilisé à l'extérieur, et ne fait pas partie de la normale "code client" de l'interface.
  3. L'utilisation de double underscore seulement pour les choses qui sont purement de commodité à l'intérieur de la classe, ou s'il cause des dégâts considérables si accidentellement exposés.

Au-dessus de tous, il devrait être clair que tout n'. Document si quelqu'un d'autre sera de l'utiliser. Le Document si vous le souhaitez pour être utile dans un an.

Comme une note de côté, vous devriez vraiment aller avec protégé dans les autres langues: Vous ne savez jamais votre classe peut être hérité plus tard, et pour ce qu'il pourrait être utilisé. Mieux que de protéger ces variables que vous êtes certain qu'il ne peut ou ne doit pas être utilisé par un code étranger.

9voto

Winston Ewert Points 17746

Vous ne devriez pas commencer avec les données privées et les rendre publiques, si nécessaire. Plutôt, vous devez commencer par trouver l'interface de votre objet. I. e. vous devez commencer par déterminer ce que le monde voit (le public) et ensuite de voir quels trucs privés est nécessaire pour le faire.

Autre langue plus difficile de rendre privé de ce qui était autrefois public. I. e. Je vais casser beaucoup de code, si je fais ma variable privés ou protégés. Mais avec des propriétés en python ce n'est pas le cas. Plutôt, je peux maintenir la même interface, même avec réorganisant les données internes.

La différence entre _ et _ _ _ _ c'est que python effectivement fait une tentative pour faire respecter ce dernier. Bien sûr, elle ne cherche pas vraiment difficile, mais il est difficile. Avoir _ simplement dit aux autres programmeurs de ce que l'intention est, ils sont libres d'ignorer à leurs risques et périls. Mais en ignorant cette règle est parfois utile. Les exemples incluent le débogage, temporaire hacks, et de travailler avec la troisième partie du code qui n'était pas destiné à être utilisé de la façon dont vous l'utilisez.

6voto

Jonathan Sternberg Points 2554

Il y a déjà beaucoup de bonnes réponses, mais je vais l'offrir à un autre. C'est aussi en partie une réponse aux personnes qui ne cessent de dire que le trait de soulignement double n'est pas privé (c'est vraiment).

Si vous regardez Java/C#, deux d'entre eux ont privé/protégé/public. Tous ces éléments sont au moment de la compilation des constructions. Ils ne sont appliquées qu'au moment de la compilation. Si vous deviez utiliser la réflexion en Java/C#, vous pouvez facilement accéder méthode privée.

Maintenant, chaque fois que vous appelez une fonction en Python, vous êtes intrinsèquement à l'aide de la réflexion. Ces morceaux de code sont les mêmes en Python.

lst = []
lst.append(1)
getattr(lst, 'append')(1)

Le "point" de la syntaxe est uniquement sucre syntaxique pour le dernier morceau de code. Principalement parce que l'utilisation de getattr est déjà moche avec un seul appel de fonction. Il ne fait que s'empirer à partir de là.

Donc, avec cela, il ne peut pas être un Java/C# version du privé, en tant que Python n'est pas à compiler le code. Java et C# ne peut pas vérifier si une fonction est privé ou public au moment de l'exécution, en tant que l'information est parti (et il n'a pas connaissance de cas où la fonction est appelée à partir d').

Maintenant, avec cette information, le nom d'une déformation de la double underscore qui fait le plus de sens pour la réalisation de "privé-ness". Maintenant, quand une fonction est appelée depuis le " moi "de l'instance et il remarque qu'il commence par"__", il effectue simplement le nom de la déformation à droite. C'est juste plus de sucre syntaxique. Que sucre syntaxique permet à l'équivalent du "privé" dans une langue qui n'utilise la réflexion pour le membre de données access.

Avertissement: je n'ai jamais entendu quelqu'un de l'Python de développement de dire quelque chose comme cela. La vraie raison de l'absence de "privé" est culturel, mais vous remarquerez aussi que plus les scripts/langages interprétés ont pas privé. Strictement exécutoire privé n'est pas pratique à rien, sauf pour le temps de compilation.

4voto

JBernardo Points 14772

D'abord: Pourquoi voulez-vous cacher de vos données? Pourquoi est-ce si important?

La plupart du temps, vous n'avez pas vraiment envie de le faire, mais vous le faites parce que les autres font.

Si vous avez vraiment vraiment vraiment ne voulez pas les gens à l'aide de quelque chose, ajouter un trait de soulignement en face d'elle. C'est ça... Pythoneux savoir que les choses avec un trait de soulignement n'est pas garanti à chaque fois et peut changer sans que vous le sachiez.

C'est la façon dont nous vivons et nous sommes d'accord avec cela.

À l'aide de deux caractères de soulignement fera de votre classe si mal à la sous-classe que même si vous ne voulez pas travailler de cette façon.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X