Les membres privés en Python
-
20-09-2019 - |
Question
Comment puis-je faire des méthodes et des membres de données privées en Python? Ou ne pas Python membres privés de soutien?
La solution
variables d'instance « privées » qui ne peut être consulté à l'exception de l'intérieur un objet, n'existe pas en Python. Cependant, il y a une convention qui est suivi par la plupart du code Python: un nom préfixé par un tiret (par exemple, _spam) devraient être traités comme une partie non publique de l'API (si elle est une fonction, une méthode ou une donnée membre). Il doit être considéré comme un détail de mise en œuvre et sous réserve changer sans préavis.
Comme il y a un cas d'utilisation valable pour les membres de la classe-privé (à savoir éviter le nom des affrontements de noms avec des noms défini par les sous-classes), il y a un support limité pour un tel mécanisme, appelé nom mutiler. tout identifiant de la forme __spam (au moins deux les traits de soulignement, au plus un underscore arrière) est textuellement remplacé par
_classname__spam
, où classname est le nom de la classe actuelle avec underscore (s) dépouillé. Ce mangling se fait sans tenir compte à la position syntaxique de la identifiant, dans la mesure où il se produit dans la définition d'une classe.
Alors, par exemple ,
class Test:
def __private_symbol(self):
pass
def normal_symbol(self):
pass
print dir(Test)
est sortie:
['_Test__private_symbol',
'__doc__',
'__module__',
'normal_symbol']
__private_symbol
doit être considérée comme une méthode privée, mais il serait encore accessible par _Test__private_symbol
.
Autres conseils
Les autres réponses fournissent les détails techniques. Je voudrais mettre l'accent sur la différence de philosophie entre Python d'une part et des langages comme C ++ / Java (que je suppose que vous êtes au courant en fonction de votre question).
L'attitude générale dans le python (Perl et pour cette matière) est que la « vie privée » d'un attribut est une demande pour le programmeur plutôt que d'une clôture en fil de fer barbelé par le compilateur / interpréteur. L'idée est bien résumé dans ce courrier et est souvent appelé comme « Nous sommes tous adultes consentants », car il suppose 'que le programmeur est assez responsable pour ne pas se mêler de l'intérieur. Les principaux underscores servent de message poli en disant que l'attribut est interne.
Par contre, si vous faire veulent accéder aux applications internes pour certaines (un exemple notable est générateurs de documentation comme pydoc), vous êtes libre de le faire. Il vous incombe en tant que programmeur de savoir ce que vous faites et le faire correctement plutôt que sur la langue pour forcer les choses que vous faites à il est chemin.
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 devraient pas être accès à certains attributs.
-
_single_leading_underscore: faible indicateur "usage interne". Par exemple.
from M import *
ne pas importer des objets dont le nom commence par un trait de soulignement. -
single_trailing_underscore_: utilisé par convention pour éviter les conflits avec mot-clé Python, par exemple
Tkinter.Toplevel(master, class_='ClassName')
-
__ double_leading_underscore: pour nommer un attribut de classe, invoque le nom calandrage (dans la classe FooBar, __boo devient _FooBar__boo; voir ci-dessous)
.
Si le nom d'une fonction Python, Procédé de classe ou attribut commence par (Mais ne se termine pas avec) deux souligne, il est privé; tout le reste est public. Python n'a pas de concept des méthodes de classe protégées (accessible seulement dans leur propre classe et descendant Des classes). Les méthodes de classe sont soit privé (accessible uniquement dans leur propre classe) ou public (accessible à partir de nulle part).
Python ne supporte pas la vie privée directement. Programmer besoin de savoir quand il est sûr de modifier l'attribut de l'extérieur mais de toute façon avec python, vous pouvez obtenir quelque chose comme privé avec des petits trucs. Maintenant, nous allons voir une personne peut mettre quoi que ce soit 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()
Quand nous exécuterons:
>>> 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 obtenir une variable commençant par un double underscore sont « traduits » en ajoutant un seul trait de soulignement et le nom de classe au début:
Remarque: Si vous ne voulez pas que ce changement de nom, mais vous voulez toujours envoyer un signal pour les autres objets de rester loin, vous pouvez utiliser un nom de soulignement initial unique avec un trait de soulignement initial ne sont pas importées avec les importations (de étoilées 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 appellerons _hello manuellement.
#test2.py from test import _hello , hello print hello() print _hello()
Sortie ->
hello hello private
Enfin: Python n'a pas vraiment un soutien équivalent vie privée, même si simple et doubles underscores initiales font dans une certaine mesure vous donner deux niveaux de la vie privée
Cela pourrait fonctionner:
import sys, functools
def private(member):
@functools.wraps(member)
def wrapper(*function_args):
myself = member.__name__
caller = sys._getframe(1).f_code.co_name
if (not caller in dir(function_args[0]) and not caller is myself):
raise Exception("%s called by %s is private"%(myself,caller))
return member(*function_args)
return wrapper
class test:
def public_method(self):
print('public method called')
@private
def private_method(self):
print('private method called')
t = test()
t.public_method()
t.private_method()
Ceci est un peu l-o-n-g réponse mais je pense qu'il arrive à la racine du problème réel ici - la portée de la visibilité. Juste accrocher là pendant que je bossez à travers cela!
Il suffit d'importer un module doit pas nécessairement donner l'accès aux développeurs d'applications à toutes ses classes ou méthodes; si je ne peux pas vraiment voir le code source du module comment vais-je savoir ce qui est disponible? Quelqu'un (ou quelque chose) doit me dire ce que je peux faire et expliquer comment utiliser ces fonctionnalités que je suis autorisé à utiliser, sinon tout cela ne sert à rien pour moi.
Les abstractions en développement plus haut niveau basé sur les classes fondamentales et méthodes via des modules importés sont présentés avec un cahier des charges DOCUMENT - PAS le code source.
La spécification du module décrit toutes les caractéristiques destinées à être visible au développeur du client. Lorsque vous traitez avec de grands projets et les équipes de projet logiciel, la mise en œuvre effective d'un module doit toujours rester caché de ceux qui l'utilisent - c'est une boîte noire avec une interface avec le monde extérieur. Pour les puristes OOD, je crois que les termes technos sont « découplage » et « cohérence ». L'utilisateur du module doit uniquement connaître les méthodes d'interface sans être charge avec les détails de la mise en œuvre.
Un module doit jamais être modifié sans d'abord changer son document de spécification sous-jacente, qui peut exiger un examen / approbation dans certaines organisations avant de modifier le code.
Comme programmeur passe-temps (maintenant à la retraite), je commence un nouveau module avec la spécification doc en fait écrit comme un bloc de commentaires géant au sommet du module, ce sera la partie que l'utilisateur voit effectivement dans la bibliothèque de spécifications. Comme il est juste moi, je n'ai pas encore mis en place une bibliothèque, mais il serait assez facile à faire.
Alors je commencer à coder en écrivant les différentes classes et méthodes, mais sans corps fonctionnels - seulement des déclarations d'impression null comme « print () » - juste assez pour permettre au module de compiler sans erreurs de syntaxe. Lorsque cette étape est terminée, je compilez le null-module complet - c'est mon spec. Si je travaillais sur une équipe de projet, je présenterais cette spécification / interface pour examen et commentaires avant de poursuivre étoffant le corps.
Je Concrétiser les corps de chaque méthode un à la fois et compilent en conséquence, assurant des erreurs de syntaxe sont fixés immédiatement à la volée. Ceci est également un bon moment pour commencer à écrire une section d'exécution « principale » temporaire en bas pour tester chaque méthode que vous coder. Lorsque le codage / tests sont terminés, tout le code de test est mis en commentaire jusqu'à ce que vous avez besoin à nouveau les mises à jour devrait être nécessaire.
Dans une équipe de développement dans le monde réel, le bloc de commentaires spec apparaît également dans une bibliothèque de contrôle des documents, mais c'est une autre histoire. Le point est:. Vous, en tant que client de module, voyez que cette spécification et pas le code source
PS: bien avant le début du temps, je travaillais dans la communauté aérospatiale de défense et nous avons fait des trucs assez cool, mais des choses comme des algorithmes propriétaires et une logique de contrôle des systèmes sensibles étaient étroitement voûté et cryptées dans les bibliothèques de logiciels sécurisé super-duper. Nous avons eu accès au module / interfaces package, mais pas les organismes de mise en œuvre de Blackbox. Il y avait un outil de gestion des documents qui a traité tous les modèles de niveau système, les spécifications logicielles, le code source et les dossiers d'essai - il a été tous ensemble synched. Le gouvernement a des exigences strictes normes d'assurance qualité des logiciels. Quelqu'un se souvient d'une langue appelée « Ada »? C'est à quel âge je suis!
J'utilise Python 2.7 et 3.5. J'ai écrit ce code:
class MyOBject(object):
def __init__(self):
self.__private_field = 10
my_object = MyOBject()
print(my_object.__private_field)
couru et a obtenu:
AttributeError: objet 'myObject' n'a pas d'attribut '__private_field'
S'il vous plaît voir: https://www.tutorialsteacher.com/python/ privé-et-accès-protégés par des modificateurs en python
si vous souhaitez effectuer une des méthodes ou des membres de données privées en Python, utiliser __setattr __
class Number:
def __init__(self,value):
self.my_private = value
def __setattr__(self, my_private, value):
# the default behavior
# self.__dict__[my_private] = value
raise Exception("can't access private member-my_private")
def main():
n = Number(2)
print(n.my_private)
if __name__ == '__main__':
main()