IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Python Discussion :

Principe d'encapsulation en python


Sujet :

Python

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éclairé
    Homme Profil pro
    Data Lover
    Inscrit en
    Décembre 2014
    Messages
    96
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Data Lover
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Décembre 2014
    Messages : 96
    Par défaut Principe d'encapsulation en python
    Bonsoir,

    Contrairement à d'autres langages de programmation comme java où le principe d'encapsulation est vraiment respecté (attribut private ou protected). En python, ce n'est pas la cas. Alors, je voudrais savoir quel serait son importance en python si on a toujours la possibilité d'accéder à une variable protégée hors classe. Par exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    class P:
     
        def __init__(self,x):
            self.__x = x
     
        def get_x(self):
            return self.__x
     
        def set_x(self, x):
            self.__x = x
     
    p1 = P(12)
    p1._P__x 
    >>>12

  2. #2
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 830
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 830
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par master4 Voir le message
    Alors, je voudrais savoir quel serait son importance en python si on a toujours la possibilité d'accéder à une variable protégée hors classe.
    Bonjour

    C'est un fait connu des programmeurs Python qui l'acceptent. Donc l'importance sera celle que toi tu lui donnes par rapport à tes besoins, ton environnement de travail (seul, en groupe), etc...
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  3. #3
    Expert confirmé

    Homme Profil pro
    Inscrit en
    Octobre 2008
    Messages
    4 307
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Octobre 2008
    Messages : 4 307
    Par défaut
    Salut,

    Ceci suit le principe qui veut que "En Python nous sommes adultes et consentants"

    Maintenant, tu peux rendre un attribut en lecture seule par divers moyens.
    Exemple:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
     
    class P:
        _instanciated = False
        def __init__(self,x):
            self.__x = x
            self.y = 6
            self._instanciated =True
     
        def __setattr__(self, name, value):
            if self._instanciated and name == '__x':
                raise NotImplementedError
            setattr(P, name, value)
     
    p = P(24)
    print(p.__x)
    print(p.y)
    p.__x = 14

  4. #4
    Expert confirmé
    Avatar de fred1599
    Homme Profil pro
    Lead Dev Python
    Inscrit en
    Juillet 2006
    Messages
    4 062
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Lead Dev Python
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Juillet 2006
    Messages : 4 062
    Par défaut
    Je suis d'accord avec Sve@r, dans le sens où tout dépendra du besoin... Après tout, tout se justifie !

    Alors pourquoi pas d'encapsulation en python,
    • Code facile à lire et à comprendre
    • La concision du code (il est inutile de faire du setter-getter et se blinder de lignes à n'en plus finir)
    • La maintenance du code facile (modifier un attribut dynamiquement est un jeu d'enfants)


    Et comme la philosophie du langage "zen of python" le dit: Simple is better than complex, tout cela tombe sous le sens.

    Maintenant si tu en as besoin, pourquoi pas, dans ce cas on utilise les property qui permettent de contrôler la lecture-écriture-suppression des attributs dans une classe. La PEP8 dit ceci,

    For simple public data attributes, it is best to expose just the attribute name, without complicated accessor/mutator methods. Keep in mind that Python provides an easy path to future enhancement, should you find that a simple data attribute needs to grow functional behavior. In that case, use properties to hide functional implementation behind simple data attribute access syntax.
    avec une petite parenthèse,

    Avoid using properties for computationally expensive operations; the attribute notation makes the caller believe that access is (relatively) cheap.
    Alors même si tu en sens le besoin, réfléchis bien ! Les conséquences sont assez nombreuses... et plus il y a de conséquences, plus on te demandera de justifier tes choix de conception. En python on cherche le maximum de simplicité, ce qui impose un maximum de responsabilité, et ça n'empêche absolument pas python d'être performant, tant dans l'écriture du code, que dans l'exécution des tâches.

  5. #5
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 830
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 830
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par VinsS Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
     
    class P:
        _instanciated = False
        def __init__(self,x):
            self.__x = x
            self.y = 6
            self._instanciated =True
     
        def __setattr__(self, name, value):
            if self._instanciated and name == '__x':
                raise NotImplementedError
            setattr(P, name, value)
     
    p = P(24)
    print(p.__x)
    print(p.y)
    p.__x = 14
    Il me semble que ton print(p.__x) ne fonctionnera pas (puisque la variable se nomme en réalité p._P__x). De même le test name == '__x' devrait plutôt être name == '_P__x'. Ceci dit j'apprécie ce code et son inventivité
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  6. #6
    Expert confirmé

    Homme Profil pro
    Inscrit en
    Octobre 2008
    Messages
    4 307
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Octobre 2008
    Messages : 4 307
    Par défaut
    Bien vu, j'ai copié la première mouture, le bon code est ceci:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
     
    class P:
        _instanciated = False
        def __init__(self,x):
            self.x = x
            self.y = 6
            self._instanciated =True
     
        def __setattr__(self, name, value):
            if self._instanciated and name == 'x':
                raise NotImplementedError
            setattr(P, name, value)
     
    p = P(24)
    print(p.x)
    print(p.y)
    p.x = 14
    et donc
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    vincent@djoliba:~/Bureau$ python3 private.py 
    24
    6
    Traceback (most recent call last):
      File "private.py", line 16, in <module>
        p.x = 14
      File "private.py", line 10, in __setattr__
        raise NotImplementedError
    NotImplementedError
    La raison d'utiliser "setattr(P, name, value)" est parce que "setattr(self, name, value)" entrainerait une récursion infinie.

  7. #7
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 830
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 830
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par VinsS Voir le message
    La raison d'utiliser "setattr(P, name, value)" est parce que "setattr(self, name, value)" entrainerait une récursion infinie.
    J'ai bien vu quand j'ai testé avec "self"

    C'est dommage car ça implique le nom de la classe dans une de ses méthodes. Si le nom change, faut reprendre le code...

    J'ai trouvé une solution pour pallier : eval("setattr(%s, %s, %s)" % (self.__class__.__name__, name, value)) (mais faut que ton objet hérite de "object") (et surtout que wiztricks ne voit jamais mon eval )...

    [edit]Euh en fait il y a un autre souci: "_instanciated" est un membre de classe statique. Il existe donc à un seul exemplaire pour toutes les instances de ton objet. Rajoute p2 = P(42) en dessous de ton p = P(24) et
    J'ai trouvé un truc mais là c'est le grand bricolage de la honte...
    Code python : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    class P(object):
    	def __init__(self, x):
    		self._instanciated=False
    		self.__x=x
    		self._instanciated=True
    	def __setattr__(self, name, value):
    		if hasattr(self, "_instanciated")\
    			and self._instanciated\
    			and name.startswith("_%s__" % self.__class__.__name__):
    			raise AttributeError("%s" % name)
    		setattr(P, name, value)
    il diffère un peu car je l'ai écrit dans le but de protéger juste les membres privés (commençant par "__")...
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  8. #8
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 738
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 738
    Par défaut
    Salut,

    Citation Envoyé par master4 Voir le message
    Alors, je voudrais savoir quel serait son importance en python si on a toujours la possibilité d'accéder à une variable protégée hors classe.
    Si vous utilisez les variables protégées de la bibliothèque X créée par le développeur D vous aurez (peut être) des soucis si, à la version suivante, le développeur D, supprime ou modifie ces variables. Comme elles ne font pas partie de l'"interface publique", il est libre de les utiliser comme il veut... Et si votre code ne fonctionne plus parce que vous n'avez pas respecté l'interface, c'est votre problème (pas le sien).

    Donc à court terme, votre code fonctionne... mais à plus long terme, il faudra (peut être) le revoir. Avec un mécanisme de protection fort, comme on le trouve dans Java ou C++, impossible d'utiliser une variable/attribut protégé. Et le risque d'avoir à revoir le code à cause de cela est nul.... et vous pouvez installer/utiliser les nouvelles versions des bibliothèques, à priori, sans risque dès que l'interface publique reste identique.

    Ceci dit, attributs privés et protégés existent bel et bien et si rien n'est testé lorsqu'on exécute un script qui accède à des attributs protégés, on peut lire le code ou l'analyser avec un pylint ou équivalent (qui testent aussi ce genre de chose).
    Donc, c'est un petit risque dont on peut se protéger, en cas de besoin.

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  9. #9
    Membre confirmé
    Homme Profil pro
    Conseil - Consultant en systèmes d'information
    Inscrit en
    Mai 2018
    Messages
    73
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Conseil - Consultant en systèmes d'information

    Informations forums :
    Inscription : Mai 2018
    Messages : 73
    Par défaut
    Citation Envoyé par master4 Voir le message
    Bonsoir,

    Contrairement à d'autres langages de programmation comme java où le principe d'encapsulation est vraiment respecté (attribut private ou protected). En python, ce n'est pas la cas. Alors, je voudrais savoir quel serait son importance en python si on a toujours la possibilité d'accéder à une variable protégée hors classe.
    Bonjour,

    Bien qu'une réponse ai été donnée, je voudrai intervenir pour préciser cette notion d'encapsulation qui n'a pas l'air d'être comprise (et c'est courant…). Je vais peut-être répéter certaines choses qui ont été écrites mais je souhaite insister sur le concept.

    L'encapsulation est un principe du paradigme "Orienté Objet". Il n'est donc pas lié à une implémentation technique et ne doit pas être confondu avec la visibilité. Un langage comme Java (que je prends en exemple du fait de mon expérience dans le domaine) met en œuvre de manière stricte la déclaration de visibilité, mais plus de 90 % du code Java en informatique de gestion n'applique pas le principe d'encapsulation (la plupart du temps parce que la conception n'est pas orientée objet).

    Le principe de l'encapsulation consiste à masquer l'implémentation d'un objet. L'erreur classique consiste à associer ce principe à une considération liée à la sécurité alors que c'est un concept lié à l'évolutivité. En séparant l'implémentation d'un objet de sa fonction, lors de la conception de cet objet, vous définissez par sa visibilité publique le contrat qui définit comment cet objet sera utilisé. Le message derrière une déclaration privée est que vous informez les utilisateurs de votre objet que pour ce composant, vous ne vous engagez pas sur son comportement extérieur. Ainsi, vous avez une conception qui vous laisse libre de l'évolution de votre implémentation sans impact sur les interfaces dont la modification de l'existant lors de l'évolution.

    Ah oui, "ce composant"…*Dans votre exemple, vous vous appuyez sur les attributs, mais l'encapsulation concerne également les méthodes. Une méthode "privée" n'est pas destinée à être appelée de l'extérieur.

    Guido Van Rossum a choisi l'approche Open-Kimono (oui, oui… ) et en soi, ce n'est pas un problème. Votre job est de fournir un objet cohérent de par sa conception pour un usage. Si vous déclarez un attribut (les objets en Python n'ont que des attributs, certains sont des callables) en privé par la convention de l'underscore et que quelqu'un appelle directement cet attribut privé, il en prend la responsabilité. Par exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    class Personne:
        def __init__(self, age):
            self.age(age)
     
        def age(valeur):
            if valeur < 0:
                raise ValueError('On ne gere que ceux qui sont deja ne')
            self._age = valeur
    Si un utilisateur de votre code fait un

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    >>> ma_personne._age = -24
    Et bien c'est sa responsabilité si le logiciel ne fonctionne pas par la suite. C'est un des principes du développement en Python : vous pouvez faire ce que vous voulez, mais assumez-en la responsabilité

    Autre point, dans votre code, vous utilisez une déclaration du type
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    _{2,}[a-zA-Z0-9_]*[a-zA-Z0-9]_?
    (oui allez, une révision des regex… :p ). Ce n'est pas une déclaration destinée à "protéger" un attribut mais à mettre en œuvre le name-mangling, une technique destinée à assurer l'unicité d'un nom principalement lors de la mise en œuvre de l'héritage.

    Respectez donc les conventions : pas de _ pour un attribut public, un _ pour déclarer que l'attribut est privé, __ pour déclarer un aspect spécial (qui dépend de la fin du nom).

  10. #10
    Membre éclairé
    Homme Profil pro
    Data Lover
    Inscrit en
    Décembre 2014
    Messages
    96
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Data Lover
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Décembre 2014
    Messages : 96
    Par défaut
    Merci @dad3zero pour cet éclaircissement

Discussions similaires

  1. [Python 2.7] accès variable depuis script principal
    Par genteur slayer dans le forum Général Python
    Réponses: 1
    Dernier message: 02/06/2016, 20h36
  2. Compréhension sur les principes en python
    Par dlasserre dans le forum Général Python
    Réponses: 4
    Dernier message: 16/03/2014, 10h30
  3. À quoi sert le principe d'encapsulation
    Par benradw dans le forum Langages de programmation
    Réponses: 1
    Dernier message: 18/10/2008, 11h42
  4. Réponses: 31
    Dernier message: 30/03/2006, 16h57
  5. [MFC](encapsulation ADO) ou placer le code
    Par philippe V dans le forum MFC
    Réponses: 2
    Dernier message: 13/06/2002, 14h58

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo