Je viens du monde Java et je lis les modèles, recettes et idiomes Python 3 de Bruce Eckels .
En lisant sur les classes, il ajoute qu'en Python, il n'est pas nécessaire de déclarer des variables d'instance. Vous les utilisez simplement dans le constructeur, et boom, 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 c'est vrai, tout objet de classe Simple
peut simplement changer la valeur de la variable en s
dehors 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 les variables publiques / privées / protégées. Ces mots-clés ont du sens parce que parfois vous voulez des variables dans une classe à laquelle personne en dehors de la classe n'a accès.
Pourquoi cela n'est-il pas requis en Python?
Réponses:
C'est culturel. En Python, vous n'écrivez pas dans l'instance ou les variables de classe d'autres classes. En Java, rien ne vous empêche de faire la même chose si vous le voulez vraiment - après tout, vous pouvez toujours modifier la source de la classe elle-même pour obtenir le même effet. Python abandonne cette prétention de sécurité et encourage les programmeurs à être responsables. En pratique, cela fonctionne très bien.
Si vous souhaitez émuler des variables privées pour une raison quelconque, vous pouvez toujours utiliser le
__
préfixe de PEP 8 . Python modifie les noms des variables comme__foo
pour qu'elles ne soient pas facilement visibles pour le code en dehors de la classe qui les contient (bien que vous puissiez le contourner si vous êtes suffisamment déterminé, tout comme vous pouvez contourner les protections de Java si vous travaillez dessus) ).Par la même convention, le
_
préfixe signifie rester à l'écart même si vous n'êtes pas techniquement empêché de le faire . Vous ne jouez pas avec les variables d'une autre classe qui ressemblent à__foo
ou_bar
.la source
Les variables privées en python sont plus ou moins un hack: l'interpréteur renomme intentionnellement la variable.
Maintenant, si vous essayez d'accéder en
__var
dehors de la définition de classe, cela échouera:Mais vous pouvez facilement vous en sortir:
Vous savez probablement que les méthodes dans la POO sont appelées comme ceci:,
x.printVar() => A.printVar(x)
si vousA.printVar()
pouvez accéder à un champ dansx
, ce champ peut également être consulté à l' extérieurA.printVar()
... après tout, les fonctions sont créées pour être réutilisables, il n'y a pas de pouvoir spécial donné aux instructions à l'intérieur.Le jeu est différent quand un compilateur est impliqué (la confidentialité est un concept au niveau du compilateur ). Il connaît la définition de classe avec les modificateurs de contrôle d'accès afin qu'il puisse générer des erreurs si les règles ne sont pas suivies au moment de la compilation
la source
Comme correctement mentionné par de nombreux commentaires ci-dessus, n'oublions pas l'objectif principal des modificateurs d'accès: aider les utilisateurs de code à comprendre ce qui est censé changer et ce qui est censé ne pas le faire. Lorsque vous voyez un champ privé, vous ne le dérangez pas. C'est donc principalement du sucre syntaxique qui est facilement atteint en Python par les _ et les __.
la source
Il existe une variation des variables privées dans la convention de soulignement.
Il y a quelques différences subtiles, mais pour des raisons de pureté idéologique du modèle de programmation, c'est assez bon.
Il existe des exemples de décorateurs @private qui implémentent plus étroitement le concept, mais YMMV. On pourrait peut-être aussi écrire une définition de classe qui utilise des méta
la source
__x
comme une variable à l'intérieur de la classeA
est en fait réécrite par le compilateur_A__x
, elle n'est toujours pas entièrement privée et est toujours accessible._A__x
, je ne vais pas la toucher. Cela pourrait être contagieux. Je m'enfuirai loin."En java, nous avons appris les variables publiques / privées / protégées"
"Pourquoi n'est-ce pas requis en python?"
Pour la même raison, il n'est pas requis en Java.
Vous êtes libre d'utiliser - ou de ne pas utiliser
private
etprotected
.En tant que programmeur Python et Java, j'ai trouvé cela
private
et ceprotected
sont des concepts de conception très, très importants. Mais en pratique, dans des dizaines de milliers de lignes de Java et Python, je ne l' ai jamais fait utiliséprivate
ouprotected
.Pourquoi pas?
Voici ma question "protégé contre qui?"
D'autres programmeurs de mon équipe? Ils ont la source. Que signifie protégé quand ils peuvent le changer?
D'autres programmeurs sur d'autres équipes? Ils travaillent pour la même entreprise. Ils peuvent - avec un appel téléphonique - obtenir la source.
Des clients? Il s'agit de programmes de travail à la carte (en général). Les clients possèdent (généralement) le code.
Alors, de qui - précisément - suis-je en train de le protéger?
la source
Comme mentionné précédemment, vous pouvez indiquer qu'une variable ou une méthode est privée en la préfixant avec un trait de soulignement. Si vous pensez que cela ne suffit pas, 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
fait en fait référence à la valeur de retour de labar
fonction plutôt qu'à la variable elle-même, et par conséquent, elle est accessible mais pas modifiée. Cependant, si quelqu'un le voulait vraiment, il pourrait simplement l'utiliser_bar
et lui attribuer une nouvelle valeur. Il n'y a aucun moyen infaillible d'empêcher quelqu'un d'accéder aux variables et méthodes que vous souhaitez masquer, comme cela a été dit à plusieurs reprises. Cependant, l'utilisationproperty
est le message le plus clair que vous pouvez envoyer qu'une variable ne doit pas être modifiée.property
peut également être utilisé pour des chemins d'accès getter / setter / deleter plus complexes, comme expliqué ici: https://docs.python.org/3/library/functions.html#propertyla source
Python a un support limité pour les identifiants privés, grâce à une fonctionnalité qui ajoute automatiquement le nom de classe à tous les identifiants commençant par deux traits de soulignement. Cela est transparent pour le programmeur, pour la plupart, mais l'effet net est que toutes les variables nommées de cette façon peuvent être utilisées comme variables privées.
Voir ici pour en savoir plus.
En général, l'implémentation de Python de l'orientation d'objet est un peu primitive par rapport à d'autres langages. Mais j'aime ça, en fait. C'est une implémentation très conceptuellement simple et qui correspond bien au style dynamique du langage.
la source
La seule fois où j'utilise des variables privées, c'est quand j'ai besoin de faire autre chose lors de l'écriture ou de la lecture de la variable et en tant que tel, je dois forcer l'utilisation d'un setter et / ou getter.
Encore une fois, cela va à la culture, comme déjà indiqué. J'ai travaillé sur des projets où la lecture et l'écriture d'autres variables de classes étaient libres pour tous. Lorsqu'une implémentation est devenue obsolète, il a fallu beaucoup plus de temps pour identifier tous les chemins de code qui utilisaient cette fonction. Lorsque l'utilisation de setters et de getters était forcée, une instruction de débogage pouvait facilement être écrite pour identifier que la méthode obsolète avait été appelée et le chemin de code qui l'appelle.
Lorsque vous êtes sur un projet où n'importe qui peut écrire une extension, informer les utilisateurs des méthodes obsolètes qui doivent disparaître dans quelques versions est donc vital pour limiter au minimum la rupture du module lors des mises à niveau.
Donc ma réponse est; si vous et vos collègues conservez un jeu de codes simple, la protection des variables de classe n'est pas toujours nécessaire. Si vous écrivez un système extensible, il devient impératif lorsque des modifications sont apportées au noyau qui doivent être détectées par toutes les extensions utilisant le code.
la source
Désolé les gars pour "ressusciter" le fil, mais j'espère que cela aidera quelqu'un:
En Python3, si vous voulez simplement "encapsuler" les attributs de classe, comme en Java, vous pouvez simplement faire la même chose comme ceci:
Pour instancier cela, procédez comme suit:
Notez que:
print(ss.__s)
lancera une erreur.En pratique, Python3 masquera le nom d'attribut global. Transformer cela comme un attribut "privé", comme en Java. Le nom de l'attribut est toujours global, mais de manière inaccessible, comme un attribut privé dans d'autres langues.
Mais n'ayez pas peur de ça. Ça n'a pas d'importance. Il fait aussi le travail. ;)
la source
les concepts privés et protégés sont très importants. Mais python - juste un outil de prototypage et de développement rapide avec des ressources limitées disponibles pour le développement, c'est pourquoi certains des niveaux de protection ne sont pas si stricts suivis en python. Vous pouvez utiliser "__" dans le membre de la classe, cela fonctionne correctement, mais ne semble pas assez bon - chaque accès à ce champ contient ces caractères.
En outre, vous pouvez remarquer que le concept OOP en python n'est pas parfait, smaltalk ou ruby beaucoup plus proche du concept OOP pur. Même C # ou Java sont plus proches.
Python est un très bon outil. Mais c'est un langage OOP simplifié. Syntaxiquement et conceptuellement simplifié. Le principal objectif de l'existence de python est d'offrir aux développeurs la possibilité d'écrire du code facilement lisible avec un niveau d'abstraction élevé de manière très rapide.
la source
Python n'a pas de variables privées comme C ++ ou Java. Vous pouvez également accéder à n'importe quelle variable membre à tout moment si vous le souhaitez. Cependant, vous n'avez pas besoin de variables privées en Python, car en Python, il n'est pas mauvais d'exposer les variables membres de vos classes. Si vous avez besoin d'encapsuler une variable membre, vous pouvez le faire en utilisant "@property" plus tard sans casser le code client existant.
En python, le trait de soulignement unique "_" 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 peut changer entre différentes versions. Vous pouvez utiliser ces méthodes / variables, mais votre code pourrait casser, si vous utilisez une version plus récente de cette classe.
Le double trait de soulignement "__" ne signifie pas une "variable privée". Vous l'utilisez pour définir des variables qui sont des "classes locales" et qui ne peuvent pas être facilement remplacées par des sous-classes. Il modifie le nom des variables.
Par exemple:
Le nom de self .__ foobar est automatiquement modifié en self._A__foobar en classe A. Dans la classe B, il est modifié en self._B__foobar. Ainsi, chaque sous-classe peut définir sa propre variable __foobar sans remplacer sa ou ses variables parents. Mais rien ne vous empêche d'accéder aux variables commençant par des doubles traits de soulignement. Cependant, la manipulation de nom vous empêche d'appeler ces variables / méthodes de manière fortuite.
Je recommande fortement de regarder Raymond Hettingers parler de "Pythons class development toolkit" de Pycon 2013 (devrait être disponible sur Youtube), ce qui donne un bon exemple pourquoi et comment vous devez utiliser @property et "__" - les variables d'instance.
la source
@property
chose fait-elle partie de Python standard, ou est-elle spécifique à un IDE?property
fonction intégrée, qui est disponible depuis python 2.2En fait, vous pouvez simuler un
C#
getter et un setter en utilisant cette astuce simple:Ensuite, utilisez-le comme dans
C#
:Il s'agit simplement de déclarer une variable locale statique dans une fonction qui jouera un rôle get / set, car c'est la seule façon de partager une variable via les méthodes get et set, sans la rendre globale pour une classe ou un fichier.
la source