95 votes

Membres privés en Python

Comment puis-je rendre les méthodes et les membres de données privés en Python ? Ou bien Python ne supporte pas les membres privés ?

2 votes

Pour ceux qui se posent la question : Guido van Rossum vient d'expliquer l'absence de "vraies" variables privées en Python : plus.google.com/115212051037621986145/posts/7wpbQTPRWft En bref : Parce que l'aspect pratique bat la pureté

108voto

jbochi Points 12280

9.6. Variables privées

Variables d'instance "privées" qui ne peuvent être accédées que depuis l'intérieur un objet, n'existent pas en Python. Cependant, il existe une convention qui est convention qui est suivie par la plupart du code Python : un nom préfixé d'un trait de soulignement (par ex. _spam) doit être traité comme une partie non publique de l'API (qu'il s'agisse d'une fonction, d'une méthode ou d'un objet). une fonction, une méthode ou un membre de données). Il doit être considéré comme un détail d'implémentation et sujet à des changement sans préavis.

Puisqu'il existe un cas d'utilisation valide pour membres privés de classe (à savoir éviter les les conflits de noms avec les noms définis par les sous-classes), il y a support limité pour un tel mécanisme, appelé "name mangling". Tout identifiant de la forme __spam (au moins deux tirets underscores en tête, au plus un soulignement de fin) est textuellement remplacé par _classname__spam où classname est le nom de la classe actuelle sans le(s) trait(s) de soulignement en tête. Ce traitement est effectué sans tenir compte de la position syntaxique de l'élément tant qu'il apparaît dans la définition d'une classe.

Donc, par exemple ,

class Test:
    def __private_symbol(self):
        pass
    def normal_symbol(self):
        pass

print dir(Test)

produira un résultat :

['_Test__private_symbol', 
'__doc__', 
'__module__', 
'normal_symbol']

__private_symbol devrait être considérée comme une méthode privée, mais elle serait toujours accessible par l'intermédiaire de la méthode _Test__private_symbol .

4 votes

Mais que faire si je ne veux pas que mon client utilise certaines méthodes (c'est à dire des méthodes qui ne concernent pas le client, comme les méthodes utilisées pour fournir un service à une méthode publique mais qui n'est pas utile étant publique).

14 votes

@appusajeev : ne les documentez pas. S'ils les utilisent, c'est leur problème.

7 votes

Les méthodes qui commencent par un ou plusieurs caractères de soulignement ne seront pas documentées, c'est-à-dire qu'elles n'apparaîtront pas lors de l'utilisation de la commande help() sur la classe dans l'interpréteur. Votre client peut toujours techniquement les utiliser, mais c'est son propre problème s'il le fait.

43voto

Noufal Ibrahim Points 32200

Les autres réponses fournissent les détails techniques. J'aimerais souligner la différence de philosophie entre Python d'une part et des langages comme C++/Java (que vous connaissez, je suppose, d'après votre question).

L'attitude générale en Python (et en Perl d'ailleurs) est que la "confidentialité" d'un attribut est une demande du programmeur plutôt qu'une barrière de barbelés par le compilateur/interprète. L'idée est bien résumée dans ce courrier et est souvent appelé "Nous sommes tous des adultes consentants" car il "suppose" que le programmeur est suffisamment responsable pour ne pas se mêler de l'intérieur. Les traits de soulignement en tête servent de message poli indiquant que l'attribut est interne.

D'autre part, si vous faire vous voulez accéder aux internes de certaines applications (un exemple notable est celui des générateurs de documentation comme pydoc), vous êtes libre de le faire. En tant que programmeur, c'est à vous de savoir ce que vous faites et de le faire correctement, plutôt qu'au langage de vous forcer à faire des choses. c'est manière.

17 votes

"plutôt que sur la langue pour vous forcer à faire les choses à sa façon." Et les indentations ? :)

0 votes

@BorisMilner Je pense que la réponse à cela serait : L'indentation rend le code lisible et aide à la compréhension, elle devient donc une bonne pratique. Limiter l'accès aux membres ne fait rien de tel. Si quoi que ce soit, cela va un peu dans la direction opposée, parce que vous devez indiquer quels membres sont privés et lesquels ne le sont pas, ce qui ajoute un encombrement visuel.

14voto

Tendayi Mawushe Points 10335

Il n'y a pas private de tout autre mécanisme de protection d'accès en Python. Il existe une convention documentée dans le Guide de style Python pour indiquer aux utilisateurs de votre classe qu'ils ne doivent pas accéder à certains attributs.

  • _single_leading_underscore : indicateur faible "d'usage interne". Par exemple from M import * n'importe pas les objets dont le nom commence par un trait de soulignement.

  • single_trailing_underscore_ : utilisé par convention pour éviter les conflits avec des mots-clés Python, par exemple Tkinter.Toplevel(master, class_='ClassName')

  • __double_leading_underscore : lors de l'attribution d'un nom à un attribut de classe, la confusion des noms est invoquée (dans la classe FooBar, __boo devient _FooBar__boo ; voir ci-dessous).

9voto

Svetlozar Angelov Points 10583

Si le nom d'une fonction Python, une méthode de classe ou un attribut Python commence par (mais ne se termine pas par) deux underscores, il est privé ; tout le reste est public. Python n'a pas de concept de méthodes de classes protégées (accessibles seulement dans leur propre classe et dans les classes classes descendantes). Les méthodes de classe sont soit privées (accessibles uniquement dans leur propre classe) ou publiques (accessibles de n'importe où).

Plongez dans Python

8 votes

En fait, il s'agit d'un détournement de nom et les variables ne deviennent pas vraiment privées. docs.python.org/tutorial/classes.html#private-variables

0 votes

Mais que faire si je ne veux pas que mon client utilise certaines méthodes (c'est à dire des méthodes qui ne concernent pas le client, comme les méthodes utilisées pour fournir un service à une méthode publique mais qui n'est pas utile étant publique).

0 votes

Dans ce cas, vous recherchez des membres "non publics", voir la réponse de jbochi.

9voto

Prashant Gaur Points 1531

Python ne supporte pas directement la confidentialité . Le programmeur doit savoir quand il est sûr de modifier un attribut de l'extérieur, mais de toute façon, avec Python, vous pouvez réaliser quelque chose comme la confidentialité avec de petites astuces. Voyons maintenant si une personne peut mettre quelque chose de privé ou non.

class Person(object):

    def __priva(self):
        print "I am Private"

    def publ(self):
        print " I am public"

    def callpriva(self):
        self.__priva()

Maintenant, quand nous allons exécuter :

\>>> p = Person()
>>> p.publ()
 I am public
>>> p.\_\_priva()
Traceback (most recent call last):
  File "", line 1, in 
    p.\_\_priva()
AttributeError: 'Person' object has no attribute '\_\_priva'
​#Explanation   : You can see  here we are not able to fetch that private method directly.
>>> p.callpriva()
I am Private
#​Explanation  : Here we can access private method inside class​

Alors comment quelqu'un peut accéder à cette variable ?
Vous pouvez faire comme :

\>>> p.\_Person\_\_priva
I am Private

wow , en fait si python reçoit toutes les variables commençant par un double soulignement sont "traduites" en ajoutant un simple soulignement et le nom de la classe au début :

Note : Si vous ne voulez pas que ce nom change mais que vous voulez quand même envoyer un signal pour que les autres objets restent à l'écart, vous pouvez utiliser un seul trait de soulignement initial les noms avec un trait de soulignement initial ne sont pas importés avec les importations étoilées (from module import *)
Exemple :

#test.py
def hello():
    print "hello"
def _hello():
    print "Hello private"

#----------------------

#test2.py
from test import *
print hello()
print _hello()

sortie-->

hello
Traceback (most recent call last):
  File "", line 1, in 
NameError: name '\_hello' is not defined

Maintenant si nous appelons _hello manuellement .

#test2.py
from test import _hello , hello
print hello()
print _hello()

sortie-->

hello
hello private

Enfin : Python ne dispose pas vraiment d'un support équivalent pour la confidentialité, bien que les initiales simples et le double soulignement initial donnent, dans une certaine mesure, deux niveaux de confidentialité.

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