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 :

Non-Virtual-Interface pattern et Python


Sujet :

Python

  1. #1
    Nouveau membre du Club
    Inscrit en
    Avril 2008
    Messages
    39
    Détails du profil
    Informations forums :
    Inscription : Avril 2008
    Messages : 39
    Points : 35
    Points
    35
    Par défaut Non-Virtual-Interface pattern et Python
    Bonjour,
    Le pattern N.V.I., pour "non virtual interface" a été proposé par Herb Sutter dans son article "Virtuality, C/C++ Users Journal, 19(3), 2001" disponible ici:

    http://www.gotw.ca/publications/mill18.htm

    En résumé, il recommande, (quand on développe en C++) de rendre les fonctions virtuelles privées, et d'écrire une interface publique non virtuelle. Pour plus de détails sur ce pattern, je vous invite à lire l'article.

    Utilisateur de python depuis peu, j'ai par réflexe appliqué les même recettes, considérée comme des bonnes pratiques dans mon langage de référence. Seulement le comportement qui en résulte n'est pas celui que j'attendais. En effet, si on considère l'exemple suivant:

    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
    class A:
        def foo(self):
            self.__foo_impl_private();
            self._foo_impl_protected();
     
        def __foo_impl_private(self):
            pass;
     
        def _foo_impl_protected(self):
            pass
     
    class B(A):
        def __foo_impl_private(self):
            print 'coin'
     
        def _foo_impl_protected(self):
            print 'coin coin'
     
    if __name__ == "__main__":
        x = B()
        x.foo()
    A l'éxécution, ce code imprime
    là ou je m'attendais à
    On peut en déduire que le fait que __foo_impl_private soit privée empêche la classe de base d'appeler l'implémentation de la classe dérivée.

    Quelqu'un peut-il m'éclairer sur ce comportement ? Il semble que l'idée préconçue selon laquelle les méthodes de classes en python se comportent comme des méthodes virtuelles en C++ soit erronée.

  2. #2
    Membre régulier
    Profil pro
    Inscrit en
    Novembre 2008
    Messages
    99
    Détails du profil
    Informations personnelles :
    Âge : 46
    Localisation : France

    Informations forums :
    Inscription : Novembre 2008
    Messages : 99
    Points : 102
    Points
    102
    Par défaut
    Salut,

    Ton problème vient du fait que tu utilises le "__" comme préfixe pour ta méthode privée. En effet, dans ce cas, python remplace "__methodname" par "__classname_methodname". Je t'invite a lire la doc ICI.

    Ton code devient donc 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
    18
    19
    20
    21
    22
     
    class A:
        def foo(self):
            self.__A_foo_impl_private();
            self._foo_impl_protected();
     
        def __A_foo_impl_private(self):
            pass;
     
        def _foo_impl_protected(self):
            pass
     
    class B(A):
        def __B_foo_impl_private(self):
            print 'coin'
     
        def _foo_impl_protected(self):
            print 'coin coin'
     
    if __name__ == "__main__":
        x = B()
        x.foo()
    Par conséquent, quand tu tu appelles B().foo(), elle appelle A().foo() qui appelle A().__A_foo_private(). Et la, la virtualisation n'entre pas en jeu puisque les méthodes n'ont plus le même nom.

    Le simple '_' est globalement reconnu comme étant la marque de visibilité pour les données interne, mais il faut faire attention avec le "__".

  3. #3
    Expert confirmé Avatar de PauseKawa
    Homme Profil pro
    Technicien Help Desk, maintenance, réseau, système et +
    Inscrit en
    Juin 2006
    Messages
    2 725
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Technicien Help Desk, maintenance, réseau, système et +
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2006
    Messages : 2 725
    Points : 4 005
    Points
    4 005
    Par défaut
    Bonjour,

    Mon c++ se limite avec le temps à hello world je vais donc rester sur la partie Python:

    La notion de privé n'existe pas en Python.
    Le double underscore sert pour éviter les conflits de nom.
    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
    24
    25
    26
    27
    28
    class A:
        def foo(self):
            self.__foo_impl_private()
            self._foo_impl_protected()
     
        def __foo_impl_private(self):
            print 'coin A'
     
        def _foo_impl_protected(self):
            print 'coin coin A'
     
    class B(A):
        def __foo_impl_private(self):
            print 'coin B'
     
        def _foo_impl_protected(self):
            print 'coin coin B'
     
    if __name__ == "__main__":
        x = B()
        print 'in B'
        print dir(x)
        x._A__foo_impl_private()
        x.foo()
        y = A()
        print 'in A'
        print dir(y)
        y.foo()
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    in B
    ['_A__foo_impl_private', '_B__foo_impl_private', '__doc__', '__module__', '_foo_impl_protected', 'foo']
    coin A
    coin A
    coin coin B
    in A
    ['_A__foo_impl_private', '__doc__', '__module__', '_foo_impl_protected', 'foo']
    coin A
    coin coin A
    Comme vous le voyez Python transforme le nom (_A__foo_impl_private) de a fonction avant de la mettre dans l'espace de nom. C'est un 'jamais sans ma permission'.
    Dans ce sens:
    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 A:
        def foo(self):
            self.__foo_impl_private()
     
        def __foo_impl_private(self):
            print 1
     
    class B(A):
        def __foo_impl_private(self):
            print 2
     
    if __name__ == "__main__":
        x = B()
        x.foo()
    Dans la logique c'est l'inverse de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    class A
    {
    int foo() { return f();}
    virtual int f() {return 2;}
    };
    class B : public A
    {
    virtual int f() {return 1;}
    };
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    B instance;
    int k = instance.foo();
    il me semble et c'est pour cela que vous n'avez pas
    lors de votre test car c'est
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
        def __foo_impl_private(self):
            pass;
    qui est exécuté.

    @+

    Edit: grilled
    Merci d'utiliser le forum pour les questions techniques.

  4. #4
    Expert éminent
    Avatar de fred1599
    Homme Profil pro
    Lead Dev Python
    Inscrit en
    Juillet 2006
    Messages
    3 823
    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 : 3 823
    Points : 7 119
    Points
    7 119
    Par défaut
    Alors tout d'abord, python, c'est pas du C++.

    Faire du Python avec C++ est une énorme erreur.

    En Python, une méthode privée n'est que succintement privée, on dira qu'elle est difficilement accessible.

    La lisibilité du code est difficile, et n'est pas du tout du style d'un code python, __var = berk.

    Le mode protégé n'existe pas en Python, seulement public ou privé.

    Toutes les méthodes sont virtuelles.

    Je le redis, penser C++ et utiliser Python est une grosse erreur, c'est une autre façon de penser, beaucoup moins de choses à gérer.

    Si certaines fois on dit qu'un code n'est pas pythonic, c'est pas pour rien...
    Celui qui trouve sans chercher est celui qui a longtemps cherché sans trouver.(Bachelard)
    La connaissance s'acquiert par l'expérience, tout le reste n'est que de l'information.(Einstein)

  5. #5
    Expert confirmé Avatar de PauseKawa
    Homme Profil pro
    Technicien Help Desk, maintenance, réseau, système et +
    Inscrit en
    Juin 2006
    Messages
    2 725
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Technicien Help Desk, maintenance, réseau, système et +
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2006
    Messages : 2 725
    Points : 4 005
    Points
    4 005
    Par défaut
    Citation Envoyé par fred1599 Voir le message
    La lisibilité du code est difficile, et n'est pas du tout du style d'un code python, __var = berk.
    J'étais sur de voir ressortir la polémique .
    Ce n'est effectivement pas dans les habitudes d'écriture mais cela existe et a son utilité. Il est vrais que la philosophie d'écriture fait que ce n'est pas très usité mais c'est comme dire 'utiliser un singleton c'est pas bien': Limiter les solutions.

    Ceci dit je plussoie sur le fait que d’essayer de faire du C++ avec Python ne mène à rien si ce n'est a s’embrouiller les idées. La comparaison faite ici entre le private c++ et __ montre bien la différence de philosophie des deux langages.

    Je m’arrête toutefois sur cette phrase:
    Le mode protégé n'existe pas en Python, seulement public ou privé.
    Pourrait on avoir un exemple ?
    Merci d'utiliser le forum pour les questions techniques.

  6. #6
    Expert éminent
    Avatar de fred1599
    Homme Profil pro
    Lead Dev Python
    Inscrit en
    Juillet 2006
    Messages
    3 823
    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 : 3 823
    Points : 7 119
    Points
    7 119
    Par défaut
    J'insiste sur le fait que placer des underscores partout est non pythonic, j'avais vu certains gourou je ne sais plus dans quel bouquin dire que ça devrait carrément être retiré du langage et que c'était carrément une erreur.

    Pourrait on avoir un exemple ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    class foo(): 
        def bar(self): pass 
        def __bar(self): pass 
     
    f = foo() 
    f.bar()   # ça fonctionne
    f.__bar() # ça fonctionne pas
    Evitez de prendre comme référence un autre langage, voir erreur 2

    Certains livres disent de ne pas utiliser les "private methods" sans de très bonnes raisons.

    Dans wikipedia, on voit ceci

    Some consider information hiding to be unpythonic
    Mais aussi

    The slogan "We're all consenting adults here" is used to describe this attitude
    Celui qui trouve sans chercher est celui qui a longtemps cherché sans trouver.(Bachelard)
    La connaissance s'acquiert par l'expérience, tout le reste n'est que de l'information.(Einstein)

  7. #7
    Expert confirmé Avatar de PauseKawa
    Homme Profil pro
    Technicien Help Desk, maintenance, réseau, système et +
    Inscrit en
    Juin 2006
    Messages
    2 725
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Technicien Help Desk, maintenance, réseau, système et +
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2006
    Messages : 2 725
    Points : 4 005
    Points
    4 005
    Par défaut
    Cela ne fait que confirmer que les deux phrases suivantes:
    Citation Envoyé par fred1599 Voir le message
    Le mode protégé n'existe pas en Python, seulement public ou privé.
    Citation Envoyé par PauseKawa Voir le message
    La notion de privé n'existe pas en Python.
    sont fausses.

    La première idée reçue lorsque l'on arrive du c++ c'est que:
    Public
    _Protected
    __Private
    Pour le Public pas de souci donc.
    Le _ est souvent considéré comme une convention d'écriture (Ce qui n'est pas tout a fait le cas comme le montre import). En fait en Python cela correspond à 'internal/don't use'. Le programmeur étant considéré comme assez responsable pour le comprendre.
    Le __ est considéré comme le private c++. Faux comme le montre l'héritage et les dir() de l'exemple si dessus. En fait il s'approche plus du protected et c'est ce qui est demandé de faire à l'interpréteur: protéger (_class__private). Mais comme dit pour _ le programmeur est responsable donc pourquoi l'utiliser ?

    Et la je me dit mais c'est quoi ces salades ? Il n'y a pas de public/protected/private, seulement Python.
    Merci d'utiliser le forum pour les questions techniques.

  8. #8
    Expert éminent
    Avatar de fred1599
    Homme Profil pro
    Lead Dev Python
    Inscrit en
    Juillet 2006
    Messages
    3 823
    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 : 3 823
    Points : 7 119
    Points
    7 119
    Par défaut
    @Pausekawa

    On est d'accord, pour moi cette façon de faire en python reste tout simplement inutile.



    Edit :

    Je rajoute dans les bonnes pratiques sur biologeek cette phrase

    Mais essayez d'éviter la forme __privée. Je ne l'utilise jamais. Faites moi confiance. Si vous l'utilisez, vous le regretterez plus tard.
    Python n'a pas de mode protégé, Alan Gauld dit

    Python has no protected mode, only the single underscore naming convention
    Il dit aussi en répondant à la question, voulez-vous vraiment créer une méthode privée?

    There are very few real cases where private methods are required and the norm in Python is for public methods, it makes for much more flexible classes
    Très peu de cas sont nécessaires pour affirmer avoir besoin d'une méthode privée et la norme en python reste l'utilisation de la visibilité publique, et qui puis est rend le code et l'utilisation des classes plus flexibles.
    Celui qui trouve sans chercher est celui qui a longtemps cherché sans trouver.(Bachelard)
    La connaissance s'acquiert par l'expérience, tout le reste n'est que de l'information.(Einstein)

  9. #9
    Nouveau membre du Club
    Inscrit en
    Avril 2008
    Messages
    39
    Détails du profil
    Informations forums :
    Inscription : Avril 2008
    Messages : 39
    Points : 35
    Points
    35
    Par défaut
    Merci pour cet éclairage et ces excellentes lectures sur les bonnes pratiques pythoniques. Là ou le c++ fait de l'encapsulation une religion, le paradigme semble différent ici. En tous cas, merci à vous!

  10. #10
    Expert confirmé Avatar de PauseKawa
    Homme Profil pro
    Technicien Help Desk, maintenance, réseau, système et +
    Inscrit en
    Juin 2006
    Messages
    2 725
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Technicien Help Desk, maintenance, réseau, système et +
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2006
    Messages : 2 725
    Points : 4 005
    Points
    4 005
    Par défaut
    C'est en effet une des grandes différences.
    C'est aussi un des points importants, avec la considération que le programmeur est responsable, qui en fait un langage attirant.
    Et ne vous inquiétez pas: Cette 'ouverture' n’empêche en rien de faire de la POO.

    Bonne découverte et @+
    Merci d'utiliser le forum pour les questions techniques.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Un problème dans les interfaces graphique de python
    Par mohamed1985 dans le forum Tkinter
    Réponses: 9
    Dernier message: 04/02/2010, 22h32
  2. Lancement interface Glade par Python
    Par Thomas51 dans le forum GTK+ avec Python
    Réponses: 1
    Dernier message: 16/02/2009, 22h16
  3. Réponses: 9
    Dernier message: 02/04/2008, 10h05
  4. [Pattern] Marker Interface Pattern
    Par Fr@ncky dans le forum Langage
    Réponses: 8
    Dernier message: 20/12/2006, 11h18
  5. Interfaces, Pattern Observer
    Par IProg dans le forum Langage
    Réponses: 8
    Dernier message: 18/12/2003, 14h11

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