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?

Était-ce utile?

La solution

  

9.6. Variables privées

     

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).

Plongez au coeur de Python

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()
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top