web-dev-qa-db-fra.com

Variables et méthodes privées dans Python

Duplicate possible:
signification d'un simple et double soulignement avant un nom d'objet en Python

Lequel dois-je utiliser _foo (un trait de soulignement) ou __bar (double soulignement) pour les membres privés et les méthodes en Python?

65
kurikintoki

Veuillez noter qu’il n’existe pas de méthode privée en Python. Le double soulignement n'est qu'un nom:

>>> class A(object):
...     def __foo(self):
...         pass
... 
>>> a = A()
>>> A.__dict__.keys()
['__dict__', '_A__foo', '__module__', '__weakref__', '__doc__']
>>> a._A__foo()

Ainsi donc __ Le préfixe est utile lorsque vous avez besoin de changer, par exemple pour ne pas entrer en conflit avec les noms situés en haut ou en dessous de la chaîne d'héritage. Pour d'autres utilisations, un soulignement simple serait mieux, à mon humble avis.

EDIT, concernant la confusion sur __, PEP-8 est tout à fait clair à ce sujet:

Si votre classe doit être sous-classée et que vous ne souhaitez pas que les sous-classes soient utilisées, pensez à les nommer avec des traits de soulignement doubles et aucun tiret de fin. Ceci appelle l'algorithme de changement de nom de Python, où le nom de la classe est mutilé dans le nom de l'attribut. Cela permet d'éviter les conflits de noms d'attributs si les sous-classes contiennent par inadvertance des attributs portant le même nom.

Note 3: Tout le monde n'aime pas les noms malins. Essayez de trouver un équilibre entre la nécessité d’éviter les conflits de noms accidentels et l’utilisation potentielle par des appelants expérimentés.

Donc, si vous ne vous attendez pas à ce que la sous-classe redéfinisse accidentellement sa propre méthode avec le même nom, ne l'utilisez pas.

68
Daniel Kluev

Le double soulignement. Il modifie le nom de manière à ce qu'il ne soit pas accessible simplement via __fieldName de l’extérieur de la classe, c’est ce avec quoi vous voulez commencer si elles sont privées. (Bien que ce ne soit pas encore très difficile d'accéder au terrain.)

class Foo:
    def __init__(self):
        self.__privateField = 4;
        print self.__privateField # yields 4 no problem

foo = Foo()
foo.__privateField
# AttributeError: Foo instance has no attribute '__privateField'

Il sera accessible via _Foo__privateField au lieu. Mais ça crie "JE SUIS PRIVÉ NE ME TOUCHEZ PAS", ce qui est mieux que rien.

37
zneak

Double soulignement. Cela modifie le nom. La variable est toujours accessible, mais c'est généralement une mauvaise idée de le faire.

Utilisez des traits de soulignement simples pour les semi-privés (indique à python "ne modifiez cela que si vous devez absolument")) et double pour un comportement totalement privé.

9
user407896