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 :

Propriétés en Python


Sujet :

Python

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2018
    Messages
    29
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2018
    Messages : 29
    Par défaut Propriétés en Python
    Bonjour à tous, je suis actuellement entrain d'apprendre la POO en Python, et plus particulièrement les propriétés et encapsulation, j'ai vu deux manières d'encapsuler :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    class User():
            def __init__(self, age):
                    self._age = age
     
            @property
            def age(self):
                    return self._age 
     
            @age.setter
            def age(self, new_age):
                    self._age = new_age
    ou alors :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    class User():
        def __init__(self, age):
            self._age = age
     
        def _getage(self):
            return self._age
     
        def _setage(self, new_age):
        	self._age = new_age
     
        age = property(_getage, _setage)
    Mais j'aimerai connaitre la différence, est-ce qu'il y a un avantage a utilisé une façon plutôt que l'autre ?

  2. #2
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 741
    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 741
    Par défaut
    Salut,

    Citation Envoyé par DevilOS7 Voir le message
    Mais j'aimerai connaître la différence, est-ce qu'il y a un avantage a utilisé une façon plutôt que l'autre ?
    Il n'y a pas de différence pour l'utilisateur de la classe, juste dans la manière de déclarer l'interface.
    Et vous voyez que @property vous impose le nom des méthodes appelées alors que property(...) vous laisse plus libre.

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

  3. #3
    Membre averti
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2018
    Messages
    29
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2018
    Messages : 29
    Par défaut
    Merci pour votre réponse
    Et en terme de conventions ou de "mode" si par la suite je dois travailler avec des autres développeurs, lequel est le plus utilisé ?

  4. #4
    Modérateur

    Avatar de Bktero
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2009
    Messages
    4 493
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2009
    Messages : 4 493
    Billets dans le blog
    1
    Par défaut
    Il y a une 3e façon :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    class User():
        def __init__(self, age):
            self.age = age
    On accède alors directement au champ :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    user = User()
    user.age
    La plupart des bonnes pratiques POO qu'on peut voir pour Java ou C++ disent que c'est "mal". Les données devraient être privées et on devrait avoir des méthodes publiques pour y accéder et les modifier. Ce sont des getters et setters. En Python, il n'y pas de visibilité publique ou privée. Nommer une donnée membre ou une méthode en commençant par un _ être une règle d'usage pour dire "c'est interne, merci de ne pas s'en servir". Donc on se retrouve souvent à faire des accès directs aux données. Python a une philosophie assez spéciale de "t'es grand tu sais ce que tu fais", donc pleines d'habitude que tu pourrais avoir en Java (par exemple) pourrait être mises à mal.

    Ta technique #2 reprend cette idée de getter et setter. Tu devrais juste enlever le _ pour les noms de fonctions : elles sont "publiques" alors que _age est la donnée "privée".

    Tu te rends bien compte que cette technique a un défaut : on peut toujours accéder à _age directement... Dans ton example, ce n'est pas grave, puisque la fonction set_age ne fait rien de plus qu'une simple affectation. Mais tu pourrais vouloir faire une fonction set_age() qui fait des vérifications sur la valeur pour la refuser si elle est négative par exemple. C'est la qu'intervient la technique #1. Tu pars souvent de ma technique et si en cours de route tu as besoin d'un setter plus évolué, tu transformes ça en property. C'est la technique la plus pythonique.

    Ces articles expliquent bien la chose :
    https://www.programiz.com/python-programming/property
    https://www.python-course.eu/python3_properties.php
    http://dauzon.com/lire-Python-Getter...otre-chemin-31 (en français si tu préfères)

    Un exemple du coup (en Python 3.6) :
    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
    18
    19
    20
    21
    22
    23
    class User:
        def __init__(self, age):
            self._age = age
     
        @property
        def age(self):
            print("Getting age")
            return self._age
     
        @age.setter
        def age(self, value):
            if value < 0:
                raise ValueError("Age below 0 is not possible")
            print("Setting value")
            self._age = value
     
    # utilisation de la classe
    c = User(50)
    print(c.age)
    c.age = 51
    print(c.age)
    c.age = -10
    print(c.age)
    Il affiche :
    Getting age
    50
    Setting value
    Getting age
    51
    Traceback (most recent call last):
    File "C:\Users\Greextpgr\Desktop\temp.py", line 21, in <module>
    c.age = -10
    File "C:\Users\Greextpgr\Desktop\temp.py", line 13, in age
    raise ValueError("Age below 0 is not possible")
    ValueError: Age below 0 is not possible

    Si on avait un champ "simple", le code d'utilisation serait les mêmes, à l'exception et aux messages de debug prêts

  5. #5
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 741
    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 741
    Par défaut
    Salut,

    Citation Envoyé par DevilOS7 Voir le message
    Et en terme de conventions ou de "mode" si par la suite je dois travailler avec des autres développeurs, lequel est le plus utilisé ?
    Si un jour vous devez travailler avec d'autres développeurs, le plus simple sera d'en discuter avec eux pour voir l'intérêt d'avoir une convention commune ou pas. Et si vous avez la chance de travailler avec des équipes différentes, vous constaterez que chacune pourra avoir ses propres conventions.

    Citation Envoyé par Bktero Voir le message
    La plupart des bonnes pratiques POO qu'on peut voir pour Java ou C++ disent que c'est "mal". Les données devraient être privées et on devrait avoir des méthodes publiques pour y accéder et les modifier. Ce sont des getters et setters.
    C'est "mal" parce que si on change d'avis (i.e. on ajoute une vérification obligeant à définir setter/getter), on passe de l'accès à un attribut à un appel de fonction (le setter/getter) et, de ce fait, çà casse l'interface (et obligera la modification des codes clients).
    Avec Python, on peut forcer l'accès à un attribut via un descripteur (et donc ajouter l'appel de fonction) sans casser l'interface.

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

  6. #6
    Membre averti
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2018
    Messages
    29
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2018
    Messages : 29
    Par défaut
    Merci pour vos réponses, mais du coup il y a toujours moyen de contourner l'encapsulation non ? (J'ai du louper quelque chose )

    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
    18
    19
    20
    21
    22
    23
     
    class User:
        def __init__(self, age):
            self._age = age
     
        @property
        def age(self):
            print("Getting age")
            return self._age
     
        @age.setter
        def age(self, value):
            if value < 0:
                raise ValueError("Age below 0 is not possible")
            print("Setting value")
            self._age = value
     
    # utilisation de la classe
    c = User(50)
    c._age = -10
    print(c.age)
     
    # Cela affiche : -10
    Et sinon plus généralement quel est l'utilité des décorateurs ? Quand les utilises-t-on ?

  7. #7
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 741
    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 741
    Par défaut
    Citation Envoyé par DevilOS7 Voir le message
    mais du coup il y a toujours moyen de contourner l'encapsulation non ? (J'ai du louper quelque chose )
    Avec un langage interprété tel que Python, difficile d'interdire quoi que ce soit... A vous d'être un adulte responsable et éviter de faire n'importe quoi.

    Citation Envoyé par DevilOS7 Voir le message
    Et sinon plus généralement quel est l'utilité des décorateurs ? Quand les utilises-t-on ?
    En POO, les décorateurs sont des patrons de conceptions. Ils n'ont rien de spécifiques à Python sinon côté sucre syntaxique (le @property) dont on peut tout à fait se passer (voir les exemples que vous avez donné dans votre post initial).

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

Discussions similaires

  1. [Python 2.X] Les propriétés en python
    Par hichem0550 dans le forum Général Python
    Réponses: 3
    Dernier message: 12/03/2017, 10h08
  2. Un nouveau shell combine Python et les propriétés de Bash
    Par Coriolan dans le forum Général Python
    Réponses: 10
    Dernier message: 14/06/2016, 13h30
  3. [ActiveX] Visibilité d'une propriété
    Par paradise dans le forum Composants VCL
    Réponses: 2
    Dernier message: 14/11/2002, 18h33
  4. [controle] propriété read only
    Par Fizgig dans le forum Composants VCL
    Réponses: 6
    Dernier message: 28/08/2002, 10h30
  5. [propriétés]Option Checked
    Par psl dans le forum Composants VCL
    Réponses: 6
    Dernier message: 22/08/2002, 08h07

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