Python ont “privé” des variables dans les classes?
Je suis venant du monde Java et la lecture de Bruce Eckels' Python 3 Modèles, des Recettes et des expressions idiomatiques.
Lors de la lecture sur les classes, c'est-à-dire qu'en Python il n'est pas nécessaire de déclarer les variables d'instance. Vous venez de les utiliser dans le constructeur, et boum, ils sont là.
Ainsi, par exemple:
class Simple:
def __init__(self, s):
print("inside the simple constructor")
self.s = s
def show(self):
print(self.s)
def showMsg(self, msg):
print(msg + ':', self.show())
Si cela est vrai, alors tout objet de la classe Simple
suffit de modifier la valeur de la variable s
à l'extérieur de la classe.
Par exemple:
if __name__ == "__main__":
x = Simple("constructor argument")
x.s = "test15" # this changes the value
x.show()
x.showMsg("A message")
En Java, nous avons appris à propos de public/privé/protégé variables. Ces mots-clés, parce que parfois vous voulez des variables dans une classe à laquelle personne n'en dehors de la classe a accès.
Pourquoi n'est-ce pas nécessaire en Python?
- Vous vouliez dire, les variables d'instance, pas de variables de classe, non?
- Vous devriez vérifier les propriétés: docs.python.org/library/functions.html#property. Utilisez simplement la lecture et de votre variable sera protégé.
Vous devez vous connecter pour publier un commentaire.
C'est culturel. En Python, tu n'écris pas pour les autres classes d'instance ou de variables de classe. En Java, rien ne vous empêche de faire de même si vous vraiment voulez - après tout, vous pouvez toujours modifier le source de la classe elle-même pour obtenir le même effet. Python que des gouttes prétexte de la sécurité et encourage les programmeurs à être responsable. Dans la pratique, cela fonctionne très bien.
Si vous souhaitez émuler les variables privées pour une raison quelconque, vous pouvez toujours utiliser le
__
préfixe de PEP 8. Python mangles les noms de variables comme__foo
de sorte qu'ils ne sont pas facilement visibles par le code de l'extérieur de la classe qui les contient (bien que vous peut obtenir autour d'elle si vous êtes assez déterminé, tout comme vous peut obtenir autour de Java protections si vous travaillez à lui).Par la même convention, la
_
préfixe signifie rester à l'écart, même si vous n'êtes pas empêché de le faire. Vous n'avez pas jouer avec une autre classe de variables qui ressemblent à des__foo
ou_bar
._
sur le nom de la variable. Python est distribué -- et exécuter -- en tant que source. Il n'existe pas.la classe de fichier pour dissimuler la mise en œuvre derrière.foo
,_foo
, et__foo
. IDEs et autres outils de soutien à ceux et appeler des références externes pour une classe de l'intérieur. Mais encore une fois, il ne veut pas le faire valoir: si vous êtes déterminé à échapper à la sandbox, eh bien, allez-y, mais la responsabilité de ne pas casser des choses sur vous.AnotherClass.__foo
, soit, comme vous l'avez pour calculer sa mise en œuvre spécifique dérivé du nom. Dans Disponible 3.5, qui pourrait ressembler àAnotherClass._AnotherClass__foo
. Bien sûr, c'est surmontable (aussi longtemps que vous savez ce que la mise en œuvre de votre code en cours d'exécution sur!) mais c'est un géant signe d'avertissement que vous ne devriez pas faire cela.someobj._attrib
vous savoir vous êtes en rupture de l'encapsulation. À partir de ce moment-là que vous prenez la pleine responsabilité pour quelque conséquence indésirable qui pourrait arriver.dir(SomeObject)
et voit une séduisante-attribut de nom qui arrive à démarrer avec un trait de soulignement, il ya une bonne chance qu'ils (ou je) vais essayer de l'utiliser. Habituellement, pour les lire, mais pourquoi ne pas mettre aussi? Je ne pense pas que n'importe quel nombre de caractères de soulignement naturellement ou n'a évidemment rien de "privé" dans le sens traditionnel du terme (et l'évidence est généralement la meilleure chose à propos de Python). Ce serait bien si ils n'apparaissent pas dans lesdir()
ouhelp()
etc., que ferait un beaucoup en plus "privé".Privé variables en python est plus ou moins un hack: l'interprète intentionnellement renomme la variable.
Maintenant, si vous essayez d'accéder à
__var
en dehors de la définition de la classe, ce sera un échec:Mais vous pouvez facilement obtenir loin avec cette:
Vous savez probablement que les méthodes en programmation orientée objet, sont invoqués comme ceci:
x.printVar() => A.printVar(x)
, siA.printVar()
pouvez accéder à un certain domainex
, ce champ peut également être consulté à l'extérieurA.printVar()
...après tout, les fonctions sont créés pour la réutilisabilité, il n'y a pas de pouvoir spécial donné les instructions à l'intérieur.Le jeu est différent quand il y a un compilateur impliqués (la vie privée est un compilateur niveau concept). Il sait à propos de la définition de la classe avec le contrôle d'accès des modificateurs de sorte qu'il peut d'erreur si les règles ne sont pas respectées au moment de la compilation
self.__dic__ = {}
n'autorise pas l'utilisation de__str__
méthode. Il y a tout un travail autour de l'utilisation__str__
dans ce contexte?AttributeError: 'A' object has no attribute '_A__var1'
Code: gist.github.com/arsho/98db85456f57b92639faedcf7aff045aget
etset
méthodes pour les champs privés, vous pouvez affirmer que ces sont pas encapsulé! Donc, clairement, l'encapsulation est une préoccupation de la conception, de la langue fonctionnalités.Comme correctement mentionné par la plupart des commentaires ci-dessus, n'oublions pas l'objectif principal de Modificateurs d'Accès: Pour aider les utilisateurs de code à comprendre ce qui est censé changer et ce qui est censé ne pas le faire. Quand vous voyez un champ privé vous ne plaisante pas avec ça. Donc, c'est principalement du sucre syntaxique qui est facilement réalisé en Python par l' _ et____.
Il y a une variation des variables privées dans le trait de soulignement de la convention.
Il ya quelques différences subtiles, mais pour des raisons de programmation modèle de la pureté idéologique, son assez bon.
Il existe de nombreux exemples de @privée décorateurs que de plus en plus étroitement mettre en œuvre le concept, mais YMMV. Sans doute on pourrait aussi écrire une classe définition qui utilise des méta
__x
comme une variable à l'intérieur de la classeA
est en fait réécrit par le compilateur pour_A__x
, il n'est pas encore entièrement privé et peut toujours être consulté._A__x
, je ne vais pas y toucher. Il pourrait être contagieux. Je vais courir loin de l'enfer il."En java, nous avons appris à propos de public/privé/protégé variables"
"Pourquoi n'est-ce pas nécessaire en python?"
Pour la même raison, il n'est pas nécessaire en Java.
Vous êtes libre de les utiliser-ou de ne pas utiliser
private
etprotected
.Comme un Python et Java programmeur, j'ai trouvé que
private
etprotected
sont très, très important de concepts de design. Mais en pratique, dans des dizaines de milliers de lignes de Java et Python, je n'ai jamais fait utiliséprivate
ouprotected
.Pourquoi pas?
Voici ma question "protégé contre qui?"
D'autres programmeurs dans mon équipe? Ils ont de la source. Ce n'est protégée de dire quand ils peuvent le changer?
D'autres programmeurs sur les autres équipes? Ils travaillent pour la même société. Ils peuvent -- avec un appel téléphonique -- obtenir le code source.
Clients? C'est le travail d'un contrat de louage de programmation (en général). Les clients (en général), propre au code.
Donc, qui, précisément -- suis-je la protéger de l'?
private
.private
est tout simplement trop peu d'informations pour être de valeur réelle.private
. Vous dites qu'il y a bien encapsulé, une bonne conception de la magie ne parvient pas à montrer une bonne encapsulation en raison de la non-utilisationprivate
? Si oui, alorsfriend
déclarations, de manière sélective supprimer la vie privée, serait de faire le design comme par magie "non encapsulées". Même si elle est bien contrôlée? Je n'achète pasprivate
== bon du tout.private
mot-clé dans une langue qui n'est certainement pas une mauvaise chose.public
/private
n' PAS signifie "tout". Il donne au membre de visibilité par défaut, ce qui signifie qu'il est visible à l'intérieur de son emballage, mais pas à partir de n'importe où ailleurs (y compris les sous-paquets). Vous ne à l'utilisation de la visibilité pour la fonctionnalité dans la plupart des cas.private
ouprotected
dans l'ensemble de votre carrière semble trop têtu. Il y a une valeur dans la communication de vos intentions pour le compilateur, en l'absence de conventions culturelles comme en Python. Dans la plupart des langues qui les prennent en charge, les autres attendent de vous les mettre à profit pour communiquer vos intentions.protected
est de la démagogie, mais ok. Donc, concernantprivate
? L'intrigue!: vaprivate
de votre interprétation va devenir un soldat de classement le plus bas? Ou vous demande programmeur seront obligés de posséder un var/méthode, mais vous êtes un communiste et sont contre la propriété privée (jeu de mots involontaire) pour les moyens de production (et de vars/les méthodes sont les moyens de production, bien évidemment)?A._no_touch = 5
approche serait la cause d'un tel codeur malveillant pour rire à ma "s'il vous plaît ne pas y toucher". MonA.__get_SSN(self)
semble être un peu utopique, en espérant que le black hat ne sais pas Zorf astuce. Je veux savoir combien je suis totalement absente des choses. Ne devrait-on pas le code pour des informations sensibles en Python? Je ne sais vraiment pas, mais j'aimerais savoir.public
,private
,protected
, et des traits de soulignement ne sont pas là pour la sécurité de l'ordinateur, ils sont ceux qui fonctionnera avec votre code de savoir ce qui appartient à la classe. Est-ce que son droit? J'ai toujours pensé que ces mots-clés ont été sur la sécurité informatique. C'est agréable d'apprendre leur utilisation réelle.Python a limité de soutien pour les identifiants, grâce à une fonctionnalité qui ajoute automatiquement le nom de la classe à tous les identificateurs commençant par deux caractères de soulignement. C'est transparent pour le programmeur, pour la plupart, mais l'effet net est que les variables nommé de cette façon peuvent être utilisées comme des variables privées.
Voir ici pour en savoir plus.
En général, le Python de la mise en œuvre de l'orientation de l'objet est un peu primitif par rapport à d'autres langues. Mais j'aime cela, en fait. C'est un concept simple de mise en œuvre et s'accorde bien avec le style dynamique de la langue.
Comme mentionné précédemment, vous pouvez indiquer qu'une variable ou une méthode est privée en préfixant avec un trait de soulignement. Si vous n'avez pas l'impression que c'est assez, vous pouvez toujours utiliser le
property
décorateur. Voici un exemple:De cette façon, quelqu'un ou quelque chose qui fait référence à
bar
est en fait le référencement de la valeur de retour de labar
fonction plutôt que la variable elle-même, et par conséquent, il peut être consulté, mais pas changé. Cependant, si quelqu'un voulait vraiment, il pourrait simplement utiliser_bar
et assigner une nouvelle valeur. Il n'y a pas de moyen infaillible pour empêcher quelqu'un d'accéder à des variables et des méthodes que vous souhaitez masquer, comme il a été dit à plusieurs reprises. Cependant, l'utilisation deproperty
est le meilleur message que vous pouvez envoyer qu'une variable est de ne pas être édité.property
peut également être utilisé pour les plus complexes des getter/setter/deleter les chemins d'accès, comme expliqué ici: https://docs.python.org/3/library/functions.html#propertyLa seule fois que j'ai utiliser des variables privées, c'est quand j'ai besoin de faire d'autres choses lors de l'écriture ou de lecture de la variable et en tant que tel j'ai besoin de forcer l'utilisation d'un setter et/ou de lecture.
De nouveau c'est une question de culture, comme déjà indiqué. J'ai travaillé sur des projets où la lecture et l'écriture d'autres classes de variables est gratuite-pour-tous. Lors de la mise en oeuvre de la est devenu obsolète, il a fallu beaucoup plus de temps pour identifier tous les chemins de code de cette fonction. Lors de l'utilisation de setters et getters a été forcé, une instruction de débogage pourrait facilement être écrit à identifier que la méthode dépréciée avait été appelé et le chemin de code qui l'appelle.
Lorsque vous êtes sur un projet où tout le monde peut écrire une extension, d'informer les utilisateurs à propos des méthodes obsolètes qui sont à disparaître dans quelques versions de ce fait, est vital pour garder module de rupture à un minimum lors de mises à niveau.
Donc, ma réponse est; si vous et vos collègues, de maintenir un simple jeu de codes de protéger de variables de classe n'est pas toujours nécessaire. Si vous écrivez un système extensible alors il devient impératif lorsque les modifications apportées à la base est fait qui doit être pris par toutes les extensions à l'aide du code.
privé et protégé concepts sont très importants. Mais python - juste un outil de prototypage rapide et de développement avec des ressources limitées disponibles pour le développement, c'est pourquoi certains niveaux de protection ne sont pas aussi stricte suivie en python. Vous pouvez utiliser "__" dans la classe membre, il fonctionne correctement, mais ne semble pas assez bon - chaque accès à ce champ contient ces caractères.
Aussi, vous pouvez remarqué que python programmation orientée objet concept n'est pas parfait, smaltalk ou ruby beaucoup plus proche de pur concept de la programmation orientée objet. Même C# ou Java sont les plus étroits.
Python est un très bon outil. Mais il est simplifié de la programmation orientée objet du langage. Du point de vue syntaxique et conceptuel simplifié. L'objectif principal de python existence est d'apporter aux développeurs la possibilité d'écrire facilement un code lisible avec un haut niveau d'abstraction dans une manière très rapide.
Désolé les gars pour "ressusciter" le fil, mais, j'espère que cela va aider quelqu'un:
En Python3 si vous voulez juste pour "encapsuler" les attributs de classe, comme en Java, il vous suffit de faire la même chose comme ceci:
Pour instancier ce faire:
Noter que:
print(ss.__s)
lèvera une erreur.Dans la pratique, Python3 doit coder le mondial le nom de l'attribut. Tourner cela comme un "privé" de l'attribut, comme dans Java. Le nom de l'attribut est toujours globale, mais sont inaccessibles façon, comme un attribut privé dans d'autres langues.
Mais ne pas avoir peur de lui. Il n'a pas d'importance. Il fait le travail aussi. 😉
Python n'a pas de variables privées comme C++ ou Java. Vous pouvez avoir accès à tout membre de la variable à tout moment si vous le souhaitez, aussi. Cependant, vous n'avez pas besoin de variables privées en Python, car en Python il n'est pas mauvais pour exposer vos classes de variables de membre. Si vous avez besoin de les encapsuler une variable membre, vous pouvez le faire en utilisant "@la propriété" plus tard, sans casser existantes code client.
En python le seul trait de soulignement "_" est utilisé pour indiquer qu'une méthode ou une variable n'est pas considérée comme faisant partie de l'api publique d'une classe et que cette partie de l'api pourrait changer entre les différentes versions. Vous pouvez utiliser ces méthodes/variables, mais votre code pourrait se briser, si vous utilisez une version plus récente de cette classe.
Le double trait de soulignement "__" ne signifie pas une "variable privée". Vous pouvez l'utiliser pour définir des variables qui sont "classe" du local et qui ne peuvent pas être facilement overidden par les sous-classes. Il mangles variables nom.
Par exemple:
auto.__foobar nom est automatiquement mutilé de soi._Un__foobar dans la classe A. Dans la classe B, il est mutilé à soi-même._B__foobar. Ainsi, chaque sous-classe peut définir sa propre variable __foobar sans écraser ses parents variable(s). Mais rien ne vous empêche d'accéder aux variables commençant par un double soulignement. Cependant, le nom d'une déformation ne vous empêche de l'appel de cette variables /méthodes d'ailleurs.
Je recommande fortement de regarder Raymond Hettingers parler "les Pythons de développement de classe toolkit" de Pycon 2013 (doit être disponible sur Youtube), ce qui donne un bon exemple de pourquoi et comment vous devez utiliser @bien et "__"-les variables d'instance.
@property
chose partie du standard de Python, ou est-il spécifique à un IDE?property
builtin fonction, qui est disponible depuis le python 2.2