Python nous donne la possibilité de créer des méthodes et des variables « privées » au sein d' une classe par préfixer doubles underscores au nom, comme celui - ci: __myPrivateMethod()
. Comment alors expliquer cela
>>> class MyClass:
... def myPublicMethod(self):
... print 'public method'
... def __myPrivateMethod(self):
... print 'this is private!!'
...
>>> obj = MyClass()
>>> obj.myPublicMethod()
public method
>>> obj.__myPrivateMethod()
Traceback (most recent call last):
File "", line 1, in
AttributeError: MyClass instance has no attribute '__myPrivateMethod'
>>> dir(obj)
['_MyClass__myPrivateMethod', '__doc__', '__module__', 'myPublicMethod']
>>> obj._MyClass__myPrivateMethod()
this is private!!
Quel est le problème?!
Je vais l'expliquer un peu à ceux qui ne l'ont pas bien compris.
>>> class MyClass:
... def myPublicMethod(self):
... print 'public method'
... def __myPrivateMethod(self):
... print 'this is private!!'
...
>>> obj = MyClass()
Ce que j'ai fait là-bas, c'est créer une classe avec une méthode publique et une méthode privée et l'instancier.
Ensuite, j'appelle sa méthode publique.
>>> obj.myPublicMethod()
public method
Ensuite, j'essaie d'appeler sa méthode privée.
>>> obj.__myPrivateMethod()
Traceback (most recent call last):
File "", line 1, in
AttributeError: MyClass instance has no attribute '__myPrivateMethod'
Tout semble bien ici; nous ne pouvons pas l'appeler. C'est, en fait, «privé». Eh bien, ce n'est pas le cas. L'exécution de dir () sur l'objet révèle une nouvelle méthode magique que python crée par magie pour toutes vos méthodes «privées».
>>> dir(obj)
['_MyClass__myPrivateMethod', '__doc__', '__module__', 'myPublicMethod']
Le nom de cette nouvelle méthode est toujours un trait de soulignement, suivi du nom de la classe, suivi du nom de la méthode.
>>> obj._MyClass__myPrivateMethod()
this is private!!
Voilà pour l'encapsulation, hein?
Dans tous les cas, j'avais toujours entendu dire que Python ne supportait pas l'encapsulation, alors pourquoi même essayer? Ce qui donne?
Réponses:
Le brouillage de nom est utilisé pour garantir que les sous-classes ne remplacent pas accidentellement les méthodes privées et les attributs de leurs superclasses. Il n'est pas conçu pour empêcher l'accès délibéré de l'extérieur.
Par exemple:
Bien sûr, il tombe en panne si deux classes différentes ont le même nom.
la source
Exemple de fonction privée
la source
self = MyClass()
self.private_function()
. : D Bien sûr, cela ne fonctionne pas en classe, mais il suffit de définir une fonction personnalisée:def foo(self): self.private_function()
function_call.startswith('self.')
.inspect.stack()[1][4][0].strip()
<- quels sont ces nombres magiques 1, 4 et 0?self = MyClass(); self.private_function()
et il échoue lorsqu'il est appelé à l'aide d'x = self.private_function()
une méthode.Quand je suis arrivé de Java à Python, je détestais ça. Cela m'a fait peur à mort.
Aujourd'hui, c'est peut-être la seule chose que j'aime le plus à propos de Python.
J'adore être sur une plate-forme, où les gens se font confiance et ne se sentent pas obligés de construire des murs impénétrables autour de leur code. Dans les langues fortement encapsulées, si une API a un bogue et que vous avez compris ce qui ne va pas, vous ne pourrez toujours pas le contourner car la méthode requise est privée. En Python, l'attitude est: "sûr". Si vous pensez comprendre la situation, vous l'avez peut-être même lue, alors tout ce que nous pouvons dire, c'est "bonne chance!".
N'oubliez pas que l'encapsulation n'est même pas faiblement liée à la «sécurité» ou au fait de garder les enfants hors de la pelouse. C'est juste un autre modèle qui devrait être utilisé pour rendre une base de code plus facile à comprendre.
la source
Sur http://www.faqs.org/docs/diveintopython/fileinfo_private.html
la source
L'expression couramment utilisée est «nous sommes tous des adultes consentants ici». En ajoutant un seul trait de soulignement (ne pas exposer) ou un double trait de soulignement (masquer), vous dites à l'utilisateur de votre classe que vous avez l'intention que le membre soit «privé» d'une manière ou d'une autre. Cependant, vous faites confiance à tous les autres pour qu'ils se comportent de manière responsable et respectent cela, sauf s'ils ont une raison impérieuse de ne pas le faire (par exemple, les débogueurs, la complétion de code).
Si vous devez vraiment avoir quelque chose de privé, vous pouvez l'implémenter dans une extension (par exemple en C pour CPython). Dans la plupart des cas, cependant, vous apprenez simplement la manière de faire les choses en Python.
la source
Ce n'est pas comme si vous ne pouviez absolument pas contourner la confidentialité des membres dans n'importe quel langage (arithmétique des pointeurs en C ++, Reflections en .NET / Java).
Le fait est que vous obtenez une erreur si vous essayez d'appeler la méthode privée par accident. Mais si vous voulez vous tirer une balle dans le pied, allez-y et faites-le.
Edit: Vous n'essayez pas de sécuriser vos affaires par encapsulation OO, n'est-ce pas?
la source
La
class.__stuff
convention de dénomination permet au programmeur de savoir qu'il n'est pas censé accéder__stuff
de l'extérieur. Le nom malmené fait qu'il est peu probable que quelqu'un le fasse par accident.Certes, vous pouvez toujours contourner cela, c'est encore plus facile que dans d'autres langues (ce que BTW vous permet également de faire), mais aucun programmeur Python ne le ferait s'il se soucie de l'encapsulation.
la source
Un comportement similaire existe lorsque les noms d'attribut de module commencent par un seul trait de soulignement (par exemple _foo).
Les attributs de module nommés comme tels ne seront pas copiés dans un module d'importation lors de l'utilisation de la
from*
méthode, par exemple:Cependant, il s'agit d'une convention et non d'une contrainte de langage. Ce ne sont pas des attributs privés; ils peuvent être référencés et manipulés par tout importateur. Certains soutiennent qu'à cause de cela, Python ne peut pas implémenter une véritable encapsulation.
la source
Ce n'est qu'un de ces choix de conception de langage. À un certain niveau, ils sont justifiés. Ils font en sorte que vous devez aller assez loin pour essayer d'appeler la méthode, et si vous en avez vraiment besoin, vous devez avoir une assez bonne raison!
Les crochets de débogage et les tests viennent à l'esprit comme des applications possibles, utilisées de manière responsable bien sûr.
la source
Avec Python 3.4, voici le comportement:
https://docs.python.org/3/tutorial/classes.html#tut-private
Même si la question est ancienne, j'espère que mon extrait de code pourrait être utile.
la source
La préoccupation la plus importante concernant les méthodes et les attributs privés est de dire aux développeurs de ne pas l'appeler en dehors de la classe et c'est l'encapsulation. on peut mal comprendre la sécurité de l'encapsulation. quand on utilise délibérément une syntaxe comme celle (ci-dessous) que vous avez mentionnée, vous ne voulez pas d'encapsulation.
J'ai migré de C # et au début, c'était bizarre pour moi aussi, mais après un certain temps, j'ai eu l'idée que seule la façon dont les concepteurs de code Python pensent à la POO est différente.
la source
Si je comprends bien, ils ne peuvent pas être privés. Comment la confidentialité pourrait-elle être respectée?
La réponse évidente est "les membres privés ne sont accessibles que par
self
", mais cela ne fonctionnerait pas -self
n'est pas spécial en Python, ce n'est rien de plus qu'un nom couramment utilisé pour le premier paramètre d'une fonction.la source