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 :

Débutant : demande d'aide sur Méthode de classe


Sujet :

Python

  1. #21
    Expert confirmé Avatar de papajoker
    Homme Profil pro
    Développeur Web
    Inscrit en
    Septembre 2013
    Messages
    2 104
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Nièvre (Bourgogne)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Septembre 2013
    Messages : 2 104
    Points : 4 454
    Points
    4 454
    Par défaut
    Citation Envoyé par fred1599 Voir le message
    En python aussi non ?
    Il ne faut pas exagérer
    Ici c'est juste une détection du type du premier paramètre et il faut quand même le même nombre de paramètres
    Donc pas viable avec le simple exemple "date" donné plus haut

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     # si défini: (s,s) (s,i)
    a.afficher("Bonjour", "toto") ok
    a.afficher("Bonjour", 45) # même que le précédent donc pas bon
    a.afficher("Bonjour") # cassé
    $moi= ( !== ) ? : ;

  2. #22
    Expert confirmé
    Avatar de popo
    Homme Profil pro
    Analyste programmeur Delphi / C#
    Inscrit en
    Mars 2005
    Messages
    2 674
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Analyste programmeur Delphi / C#
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2005
    Messages : 2 674
    Points : 5 259
    Points
    5 259
    Par défaut
    Citation Envoyé par fred1599 Voir le message
    Dans tout cela on pourrait se poser la question de savoir si ce que tu appelles statique est équivalent à une classmethod ou staticmethod en python ?
    C'est justement sur ce sujet que j'y avais vu une confusion...
    Pour moi, c'est équivalent à staticmethod.

    Si j'ai bien compris, en python, staticmethod et classmethod font sensiblement la même chose.
    Sauf que staticmethod ne peut pas modifier ou accéder à aucune propriété de classe ou d'instance, tandis que classmethod peut accéder et modifier la classe et ses propriétés.
    Ce qui semble se confirmer par mon petit essai.
    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
    class MyClass:
        # Un attribut de classe
        attr = 0
     
        @staticmethod
        def static_method():
            print("Ceci est une méthode statique")
     
        @classmethod
        def class_method(cls):
            print("Ceci est une méthode de classe")
            cls.attr += 1
            print("attr:", cls.attr)
     
    # Appel des méthodes
    MyClass.static_method()  # Affiche: Ceci est une méthode statique
    MyClass.class_method()   # Affiche: Ceci est une méthode de classe
                             #           attr: 1
    MyClass.class_method()   # Affiche: Ceci est une méthode de classe
                             #           attr: 2
    Cette notion de classmethod, qui s'utilise comme une statique mais qui donne accès aux membres de la classe, n'existe pas dans les autres langages POO que je connais.
    J'ai eu pas mal de prises de becs avec certains membres sur des notions de POO à la mode python que me semblaient étranges.
    Du coup, je laisserai les spécialistes confirmer si j'ai bien compris la nuance.

    Citation Envoyé par fred1599 Voir le message
    Tiens c'est intéressant, quelles sont les POO existantes ?
    J'en vois au moins trois (quatre si je considère comme différent les langages POO qui autorises l'héritage multiple et ceux qui ne le font pas) :
    La POO par prototype (celle je javascript par exemple).
    La POO que je qualifierait de classique (utilisé Delphi, C#, VB.Net, entre autres).
    La POO selon python (car si tout est accessible, il n'y a plus réellement de principe d'encapsulation).

  3. #23
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 287
    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 287
    Points : 36 776
    Points
    36 776
    Par défaut
    Citation Envoyé par popo Voir le message
    Si j'ai bien compris, en python, staticmethod et classmethod font sensiblement la même chose.
    Si j'écris:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    >>> class A:
    ...     @staticmethod
    ...     def f(): pass
    ...     @classmethod
    ...     def g(cls): pass
    ...     def h(self): pass
    ...
    La différence entre f, g et h sera que f est de type 'function' alors que g et h sont de type 'method'.
    Et ce foutu type 'method' est un objet qui associe une 'function' (accessible via l'attribut __func__) à un objet (via l'attribut __self__):
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    >>> a = A()
    >>> m = a.g
    >>> m.__func__, m.__self__
    (<function A.g at 0x000001B596933E20>, <class '__main__.A'>)
    >>> m = a.h
    >>> m.__func__, m.__self__
    (<function A.h at 0x000001B596933EC0>, <__main__.A object at 0x000001B59692A250>)
    >>>
    De plus 'method' est un 'callable' particulier puisque method(...) se traduira pas l'appel de method.__func__ avec method.__self__ comme premier argument.

    Et accessoirement, on pourra fabriquer un 'method' dynamiquement:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    >>> from types import MethodType
    >>> def z(o, *args): print(o, args)
    ...
    >>> zz = MethodType(z, '**')
    >>> zz(1,2,3)
    ** (1, 2, 3)
    >>>
    Pour le reste, comme pour tout sujet, il y a toujours plusieurs façons de résoudre un problème. Si ça passe par l'utilisation de classmethod, pourquoi pas... et si classmethod donne des boutons à certains pour qu'ils évitent de... et utilisent autre chose, pourquoi pas.

    Si on écrit une application, c'est pour leurs utilisateurs et ils se foutent pas mal de tout ça (et même du langage utilisé pour coder le truc). Côté développeur on essaie de faire vite et bien quelque chose de cohérent, histoire de ne pas trop galérer aux étapes évolutions/maintenance.

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

  4. #24
    Expert confirmé Avatar de papajoker
    Homme Profil pro
    Développeur Web
    Inscrit en
    Septembre 2013
    Messages
    2 104
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Nièvre (Bourgogne)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Septembre 2013
    Messages : 2 104
    Points : 4 454
    Points
    4 454
    Par défaut
    Citation Envoyé par wiztricks Voir le message
    Si ça passe par l'utilisation de classmethod, pourquoi pas... et si classmethod donne des boutons à certains pour qu'ils évitent de... et utilisent autre chose, pourquoi pas.
    Pour moi, l'unique problème est la dépendance "dure" avec des attributs publiques externes (de classe et fonctions statiques)

    histoire de ne pas trop galérer aux étapes évolutions/maintenance.
    C'est donc uniquement un problème de dépendance si on désire faire du code SOLID (principe poo pour "ne pas trop galérer aux étapes évolutions/maintenance")

    ----------
    EDIT pour wiztricks
    "publique" : oops, il valait comprendre externe
    pour reprendre l'exemple du tuto, avoir des date.fromString(xxx) dans 36 fichiers
    $moi= ( !== ) ? : ;

  5. #25
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 287
    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 287
    Points : 36 776
    Points
    36 776
    Par défaut
    Citation Envoyé par papajoker Voir le message
    Pour moi, l'unique problème est la dépendance "dure" avec des attributs publiques (de classe et fonctions statiques)
    Avec Python, tous les attributs sont publics ou plutôt, on n'a pas vraiment de moyen de forcer la visibilité des attributs en dehors de conventions de nommages (et un peu plus avec les "__").

    On peut être frustré par une fonctionnalité qui n'existe pas, mais en dépendre, je ne vois pas.

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

  6. #26
    Expert confirmé
    Avatar de popo
    Homme Profil pro
    Analyste programmeur Delphi / C#
    Inscrit en
    Mars 2005
    Messages
    2 674
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Analyste programmeur Delphi / C#
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2005
    Messages : 2 674
    Points : 5 259
    Points
    5 259
    Par défaut
    Citation Envoyé par wiztricks Voir le message
    La différence entre f, g et h sera que f est de type 'function' alors que g et h sont de type 'method'.
    Et ce foutu type 'method' est un objet qui associe une 'function' (accessible via l'attribut __func__) à un objet (via l'attribut __self__):
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    >>> a = A()
    >>> m = a.g
    >>> m.__func__, m.__self__
    (<function A.g at 0x000001B596933E20>, <class '__main__.A'>)
    >>> m = a.h
    >>> m.__func__, m.__self__
    (<function A.h at 0x000001B596933EC0>, <__main__.A object at 0x000001B59692A250>)
    >>>
    De plus 'method' est un 'callable' particulier puisque method(...) se traduira pas l'appel de method.__func__ avec method.__self__ comme premier argument.
    J'en déduis qu'il y a une notion supplémentaire qui m'a échappée.
    Ce qui est déclaré en classmethod est partagé entre toutes les instances de la classe A.

    Du coup, j'ai poussé l'expérimentation un peu plus loin pour vérifier.
    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 MyClass:
        # Un attribut de classe
        attr = 0
     
        @staticmethod
        def static_method():
            print("Ceci est une méthode statique")
     
        @classmethod
        def class_method(cls):
            print("Ceci est une méthode de classe")
            cls.attr += 1
            print("attr:", cls.attr)
     
    MyClass.static_method()
    MyClass.class_method()
    MyClass.class_method()
    a=MyClass()
    b=MyClass()
    a.static_method()
    a.class_method()
    b.static_method()
    b.class_method()
    Et je constate effectivement que mes instances a et b partagent attr.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    Ceci est une méthode statique
    Ceci est une méthode de classe
    attr: 1
    Ceci est une méthode de classe
    attr: 2
    Ceci est une méthode statique
    Ceci est une méthode de classe
    attr: 3
    Ceci est une méthode statique
    Ceci est une méthode de classe
    attr: 4
    Je confirme que ce concept est totalement (et logiquement) absent de la POO basée sur le principe d'encapsulation (Edit : en tout cas sur ceux que je pratique).
    Mais je peux aisément y voir un intérêt car ça rends moins complexe certaines problématiques.

  7. #27
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 287
    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 287
    Points : 36 776
    Points
    36 776
    Par défaut
    Citation Envoyé par popo Voir le message
    Je confirme que ce concept est totalement (et logiquement) absent de la POO basée sur le principe d'encapsulation.
    En C++, on retrouve cela (un équivalent de classmethod Python) via l'attribut "static".

    En C++, l'encapsulation est réalisée via le masquage des données (private, protected,...).
    Ce sont 2 concepts différent.

    Encapsulation qui existe aussi avec Python pourvu que les utilisateurs coopèrent et respectent les conventions de nommages.

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

  8. #28
    Membre expérimenté
    Avatar de MPython Alaplancha
    Homme Profil pro
    Paysan à 3 francs six sous
    Inscrit en
    Juin 2018
    Messages
    870
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Pyrénées Orientales (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Paysan à 3 francs six sous
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : Juin 2018
    Messages : 870
    Points : 1 522
    Points
    1 522
    Billets dans le blog
    4
    Par défaut
    Bonjour,
    Pour ma part, je n'ai jamais utilisé et éprouvé le besoin d'utiliser ces décorateurs . Probablement que je n'en saisi pas l'intérêt . J'imagine que si cela existe cela n'est pas pour rien.
    Si je souhaite que la valeur de attributs ne soit pas liés à une instance spécifique je me contente de :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    class MyClass:
        attr = 0
        def __init__(self):
            pass
        def increment_attr(self):
            MyClass.attr += 1
            print("attr=", MyClass.attr)
     
    a = MyClass()
    b = MyClass()
    a.increment_attr()
    b.increment_attr()
    En ce qui concerne @staticmethod , pourquoi vouloir appeler une méthode comme une fonction?
    #Rien de nouveau sous le soleil, tout est vanité comme courir après le vent!
    Developpement pour Android avec Python3/Kivy/Buildozer

  9. #29
    Expert confirmé
    Avatar de popo
    Homme Profil pro
    Analyste programmeur Delphi / C#
    Inscrit en
    Mars 2005
    Messages
    2 674
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Analyste programmeur Delphi / C#
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2005
    Messages : 2 674
    Points : 5 259
    Points
    5 259
    Par défaut
    Citation Envoyé par wiztricks Voir le message
    En C++, on retrouve cela (un équivalent de classmethod Python) via l'attribut "static".
    En bien non, justement.
    En C++, static est l'équivalent du staticmethod de python.
    Il n'existe pas d'équivalent direct de classmethod en C++

    Citation Envoyé par wiztricks Voir le message
    En C++, l'encapsulation est réalisée via le masquage des données (private, protected,...).
    Ce sont 2 concepts différent.

    Encapsulation qui existe aussi avec Python pourvu que les utilisateurs coopèrent et respectent les conventions de nommages.

    - W
    On a déjà eu ce débat.
    On ne tombera jamais d'accord sur ce point parce qu'on a pas la même notion de ce qu'est l'encapsulation.
    Tu as une vision purement python de la chose (logique dans un forum python me diras-tu).
    Mais puisqu'on parle des différences entre python et les autres langages, cette vision est en contradiction avec celle de C++ que tu as cité.
    En C++, cela ne se limite pas à masquer des membres de la classe.
    En C++, l'encapsulation garantit également l'étanchéité entre deux instances d'une même classe, ce qui est exactement l'inverse de ce que provoque l'utilisation de classmethod en python.
    Et c'est la raison pour laquelle il n'existe pas d'équivalent direct de classmethod en C++.
    Pas direct, car cela peux se programmer si la méthode static passe par l'utilisation d'autre objet (comme un singleton)

  10. #30
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 287
    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 287
    Points : 36 776
    Points
    36 776
    Par défaut
    Citation Envoyé par Hominidé Voir le message
    En ce qui concerne @staticmethod , pourquoi vouloir appeler une méthode comme une fonction?
    La question est plutôt dans l'intérêt de ranger une fonction dans la boîte "class" plutôt qu'à côté.... et ce faisant d'ajouter de la magie (le décorateur staticmethod) pour que cela soit possible.

    Citation Envoyé par Hominidé Voir le message
    Si je souhaite que la valeur de attributs ne soit pas liés à une instance spécifique je me contente de :
    Si je veux que les instances d'une classe partagent un même objet mutable:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    class A:
         def __init__(self, shared_object,...):
              self.shared_object = shared_objet
              ....
    c'est alors l'utilisateur de la classe qui fournit cela (peut être faudra-t-il en valider le type).
    Si je ne veux pas dépendre de l'utilisateur (de la classe), l'attribut de class fait l'affaire.

    Si l'objet n'est pas mutable, c'est une autre paire de manche car un malencontreux self.objet += 1 au lieu d'un type(self).objet += 1 foutra la grouille.

    On peut limiter le techniquement faisable en s'imposant quelques règles d'utilisation/repères (valeur par défaut si non mutable, collection partagée sinon).... quelque part, on doit maîtriser ce qu'on utilise quitte à ne pas profiter de tout son potentiel.

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

  11. #31
    Expert confirmé Avatar de papajoker
    Homme Profil pro
    Développeur Web
    Inscrit en
    Septembre 2013
    Messages
    2 104
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Nièvre (Bourgogne)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Septembre 2013
    Messages : 2 104
    Points : 4 454
    Points
    4 454
    Par défaut
    Citation Envoyé par Hominidé Voir le message
    Probablement que je n'en saisi pas l'intérêt .
    Il a été donné dans l'exemple du tuto, c'est d'utiliser sa classe comme un singleton (c'est cela mon problème de dépendance), dans ton exemple, écrire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    MyClass.increment_attr()
    #MyClass.increment_attr(None)  # add None avec ton code ...
    L'exemple était une fabrique (Nous n'avons donc pas encore d'instance de la classe sous la main), donc avec ton exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    a = MyClass.create_from_truc(args)
    j'avais aussi donné Path parmi les existants dans la lib python :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    from pathlib import Path
    path_ = Path.home()
    --------------

    Ton exemple ne tient pas compte de l'héritage, il n'est pas rare d'avoir une autre valeur pour l'attribut de classe !
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    class MyClassPlus(MyClass):
        attr = 100
    Et ici, tu n'incrémentes pas le bon attribut
    $moi= ( !== ) ? : ;

  12. #32
    Membre expérimenté
    Avatar de MPython Alaplancha
    Homme Profil pro
    Paysan à 3 francs six sous
    Inscrit en
    Juin 2018
    Messages
    870
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Pyrénées Orientales (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Paysan à 3 francs six sous
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : Juin 2018
    Messages : 870
    Points : 1 522
    Points
    1 522
    Billets dans le blog
    4
    Par défaut
    @wiztricks :
    yes

    @papajocker:
    Désolé, je n'ai pas pris en compte le contexte ... Je réagissais juste au message #22
    Je prendrai le temps de relire tout cela et je reviendrai à vous (vs tous) si besoin
    #Rien de nouveau sous le soleil, tout est vanité comme courir après le vent!
    Developpement pour Android avec Python3/Kivy/Buildozer

  13. #33
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 287
    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 287
    Points : 36 776
    Points
    36 776
    Par défaut
    Citation Envoyé par popo Voir le message
    En C++, static est l'équivalent du staticmethod de python.
    Il n'existe pas d'équivalent direct de classmethod en C++
    Si vous le dites. On peut regarder les cas d'utilisation (comment on s'en sert) et se faire une opinion comme avec ce tuto.
    note: la subtilité est dans les espaces de noms.


    Citation Envoyé par popo Voir le message
    On ne tombera jamais d'accord sur ce point parce qu'on a pas la même notion de ce qu'est l'encapsulation.
    L'encapsulation en POO est bien définie et si on veut partir de quelque chose assez large, on peut s'arrêter à la définition de wikipedia. (et ça parle bien de visibilité et de masquage d'attributs).

    Après on prend un langage OO et on a le curseur encapsulation qui pourra aller de 0 à 5.
    Sûr que si on met le curseur à 5 pour C++/Java/... on ne mettra pas 5 à Python mais on ne mettra pas 0 non plus (car il n'y a pas rien).
    Après si votre point est de dire que soit le curseur est à 5 soit il est 0, ça me semble un peu binaire... mais votre point de vue se respecte.

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

  14. #34
    Expert confirmé
    Avatar de popo
    Homme Profil pro
    Analyste programmeur Delphi / C#
    Inscrit en
    Mars 2005
    Messages
    2 674
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Analyste programmeur Delphi / C#
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2005
    Messages : 2 674
    Points : 5 259
    Points
    5 259
    Par défaut
    Citation Envoyé par wiztricks Voir le message
    Si vous le dites. On peut regarder les cas d'utilisation (comment on s'en sert) et se faire une opinion comme avec ce tuto.
    note: la subtilité est dans les espaces de noms.
    Je constate que ce tuto dit exactement la même chose, la méthode statique ne peux pas accéder aux membres non statiques de la classe.
    Donc c'est bien l'équivalent de staticmethod.

    Citation Envoyé par wiztricks Voir le message
    L'encapsulation en POO est bien définie et si on veut partir de quelque chose assez large, on peut s'arrêter à la définition de wikipedia. (et ça parle bien de visibilité et de masquage d'attributs).

    Après on prend un langage OO et on a le curseur encapsulation qui pourra aller de 0 à 5.
    Sûr que si on met le curseur à 5 pour C++/Java/... on ne mettra pas 5 à Python mais on ne mettra pas 0 non plus (car il n'y a pas rien).
    Après si votre point est de dire que soit le curseur est à 5 soit il est 0, ça me semble un peu binaire... mais votre point de vue se respecte.

    - W
    Tu le dis toi même "et si on veut partir de quelque chose assez large, on peut s'arrêter à la définition de wikipedia.".
    On peut s'y arrêter si on veut, mais ça va plus loin.
    L'article de Wikipédia est (sans doute volontairement pour toucher le plus grand nombre de langage) très générique.
    Mais ça va plus loin.

    Je n'ai jamais dit que le curseur de python sur l'encapsulation était à 0.
    Ce que j'ai dit c'est qu'il n'est pas à 5, et que ça ne correspond pas à ma définition (que tu sembles trouver trop stricte) de l'encapsulation.
    Chacun met le curseur où il veux.

    Je trouve que python a quelques avantages.
    Sa syntaxe est simple, son écriture impose l'indentation et les erreurs retournées sont claires et précises.
    C'est génial pour apprendre les bases, et d'ailleurs lorsque j'enseigne, je commence aujourd'hui par montrer les bases avec python.

    Mais justement, ce qui fait sa force, fait également sa faiblesse.
    A vouloir rester simple, python est trop permissif selon moi.

    Tu l'as dit toi même, en python ça repose sur une convention que tout le monde est sensé connaître et respecter.
    Sauf qu'en réalité, ce n'est pas forcément le cas, surtout quand on débute.
    J'ai découvert Python avec Swinnen.
    Et si le mot "convention" est présent 22 fois (j'ai vérifié), il ne fait jamais référence à la portée d'un membre d'une classe.
    Les seuls méthodes commençant par un underscore sont les __init__.

    Et d'ailleurs Swinnen dit (page 148)
    Citation Envoyé par Gérard Swinnen
    Nous pouvons changer les propriétés d'un objet en assignant de nouvelles valeurs à ses attributs.
    Par exemple, nous pouvons modifier la taille d'un rectangle (sans modifier sa position), en réassignant ses attributs hauteur et largeur.
    Nous pouvons faire cela sous Python, parce que dans ce langage les propriétés des objets sont toujours publiques
    C'est pour cela que quand je dois enseigner l'objet, je choisis volontairement un langage où le curseur est à 5 de manière stricte pour enseigner tous les aspects de la POO.

  15. #35
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 287
    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 287
    Points : 36 776
    Points
    36 776
    Par défaut
    Citation Envoyé par popo Voir le message
    Je constate que ce tuto dit exactement la même chose, la méthode statique ne peux pas accéder aux membres non statiques de la classe.
    Donc c'est bien l'équivalent de staticmethod.
    une classmethod n'accède qu'aux attributs de classe (pas à ceux d'une instance) tout comme une méthode static de C++ accède aux attributs static de la classe.
    Une static method python n'a d'accès qu'aux variables globales et aux paramètres passés.
    Dyslexique peut être?

    Citation Envoyé par popo Voir le message
    Chacun met le curseur où il veux.
    Si on essaie d'avoir des critères objectifs pour positionner le curseur, c'est qu'on ne le mets pas où on veut.

    Citation Envoyé par popo Voir le message
    C'est pour cela que quand je dois enseigner l'objet, je choisis volontairement un langage où le curseur est à 5 de manière stricte pour enseigner tous les aspects de la POO.
    Python est un langage de programmation pour adultes consentants. De fait, il demande une certaine maturité pour ne pas faire n'importe quoi et il est peut être plus raisonnable d'être cornaqué par un compilo. pour se forcer à...

    Mais tout ça revient à dire qu'on n'utilisera pas le langage X pour faire tout et n'importe quoi... (et c'est aussi vrai pour python que C++/C, Java,...)

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

  16. #36
    Expert confirmé
    Avatar de popo
    Homme Profil pro
    Analyste programmeur Delphi / C#
    Inscrit en
    Mars 2005
    Messages
    2 674
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Analyste programmeur Delphi / C#
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2005
    Messages : 2 674
    Points : 5 259
    Points
    5 259
    Par défaut
    Citation Envoyé par wiztricks Voir le message
    une classmethod n'accède qu'aux attributs de classe (pas à ceux d'une instance) tout comme une méthode static de C++ accède aux attributs static de la classe.
    Une static method python n'a d'accès qu'aux variables globales et aux paramètres passés.
    Dyslexique peut être?
    Non, simplement désorienté.
    La grosse majorité des langages POO ont un mot clé pour désigner une variable statique.
    En python c'est l'absence de self qui en fait une variable statique (donc l'inverse).
    Du coup puisque python sait distinguer une variable statique d'une variable d'instance, pourquoi avoir besoin de classmethod ?


    Citation Envoyé par wiztricks Voir le message
    Si on essaie d'avoir des critères objectifs pour positionner le curseur, c'est qu'on ne le mets pas où on veut.
    C'est justement là où je veux en venir.
    C'est en appliquant des critères objectifs qu'on peut déterminer la position du curseur de manière objective (et non là où ça nous fait plaisir).


    Citation Envoyé par wiztricks Voir le message
    Python est un langage de programmation pour adultes consentants. De fait, il demande une certaine maturité pour ne pas faire n'importe quoi et il est peut être plus raisonnable d'être cornaqué par un compilo. pour se forcer à...

    Mais tout ça revient à dire qu'on n'utilisera pas le langage X pour faire tout et n'importe quoi... (et c'est aussi vrai pour python que C++/C, Java,...)

    - W
    Nous avons toujours été d'accord sur ce point.

    Mais tu sembles avoir oublié ce que c'est de débuter.
    Tu pratiques python depuis des années, donc ce comportement ne te choques pas.
    De mon coté j'ai assez d'expérience pour trouver bizarre qu'une méthode soit accessible alors qu'elle ne le devrait pas et je saurais flairer le piège même si je n'ai pas connaissance de la convention.
    Mais un débutant n'en a pas conscience, je le sais d'expérience. Je le constate régulièrement.

    Et c'est justement pour ça que je n'enseigne pas l'objet avec Python.
    Il lui manque les garde-fous d'un langage comme C# ou Java.
    L'absence de ces garde-fous n'aident pas le débutant à comprendre lorsqu'il fait la bêtise d'appeler une méthode qu'il ne devrait pas appeler.

  17. #37
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 287
    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 287
    Points : 36 776
    Points
    36 776
    Par défaut
    Citation Envoyé par popo Voir le message
    Non, simplement désorienté.
    La grosse majorité des langages POO ont un mot clé pour désigner une variable statique.
    En python c'est l'absence de self qui en fait une variable statique (donc l'inverse).
    Du coup puisque python sait distinguer une variable statique d'une variable d'instance, pourquoi avoir besoin de classmethod ?
    Python n'est pas compilé: pas facile de récupérer l'objet (class ou instance) auquel va s'appliquer une méthode. D'où, c'est explicitement récupéré dans le premier argument de la fonction correspondante. Avec un langage compilé, c'est implicite.

    Citation Envoyé par popo Voir le message
    C'est en appliquant des critères objectifs qu'on peut déterminer la position du curseur de manière objective (et non là où ça nous fait plaisir).
    A mais si on dit que Java et C++ sont à 5 et que Python n'est pas à 0, ça me va bien... ça veut dire aussi qu'on peut un peu parler d'encapsulation avec Python même si ce n'est pas aussi satisfaisant que ce qu'on trouve ailleurs.

    Citation Envoyé par popo Voir le message
    Mais tu sembles avoir oublié ce que c'est de débuter.
    Tu pratiques python depuis des années, donc ce comportement ne te choques pas.
    De mon coté j'ai assez d'expérience pour trouver bizarre qu'une méthode soit accessible alors qu'elle ne le devrait pas et je saurais flairer le piège même si je n'ai pas connaissance de la convention.
    Python n'est pas mon premier langage de programmation. Si on s'amuse à faire de la POO "classique" avec Python, on sera désorienté par le manque d'intérêt de nombre de patterns de conception qu'on doit appliquer dans d'autres langages.
    Dit autrement, python n'est peut être pas le langage le plus adapté pour apprendre une POO dite "académique".... mais personnellement, je m'en fous un peu (désolé).

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

  18. #38
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 690
    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 690
    Points : 30 985
    Points
    30 985
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par popo Voir le message
    En python c'est l'absence de self qui en fait une variable statique (donc l'inverse).
    C'est plutôt le fait qu'elle soit créée en dehors de toute méthode qui en fait une variable statique.

    Citation Envoyé par popo Voir le message
    Du coup puisque python sait distinguer une variable statique d'une variable d'instance, pourquoi avoir besoin de classmethod ?
    Une fonction classmethod permet de créer une méthode particulière qui recevra non pas une instance d'objet mais la description de l'objet (info que n'aura pas la méthode statique)
    Imagine une date...
    Code python : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    class date:
    	def __init__(self, jj, mm, aa):
    		self.jj=jj
    		self.mm=mm
    		self.aa=aa
     
    >>> a=date(1, 1, 2000)
    >>> print(a.jj, a.mm, a.aa)
    1 1 2000

    Tu veux lui rajouter un "fromString()" permettant de récupérer la date depuis une string. Tu pourrais être tenté d'écrire cette méthode comme statique, traitant la chaine et retournant une date...
    Code python : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    class date:
    	def __init__(self, jj, mm, aa):
    		self.jj=jj
    		self.mm=mm
    		self.aa=aa
            @staticmethod
    	def fromString(string):
    		(jj, mm, aa)=string.split("/")
    		return date(jj, mm, aa)
     
    >>> a=date.fromString("1/1/2000")
    >>> print(a.jj, a.mm, a.aa)
    1 1 2000

    Le souci principal de cette façon de faire c'est que ton "fromString" ne gère pas l'héritage.
    Code python : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    class subDate(date): pass
     
    >>> a=subDate.fromString("1/1/3000")
    >>> type(a)
    <class '__main__.date'>				# Je voulais obtenir un subDate !!!

    Pour solutionner ce soucis, tu crées une classmethod qui va récupérer la classe qui l'invoque (pas l'instance, la classe elle-même). Connaissant la classe, elle pourra alors l'utiliser pour créer une instance adaptée.
    Code python : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    class date:
    	def __init__(self, jj, mm, aa):
    		self.jj=jj
    		self.mm=mm
    		self.aa=aa
            @classmethod
    	def fromString(cls, string):
    		return cls(*string.split("/"))
     
    class subDate(date): pass
     
    >>> a=subDate.fromString("1/1/3000")
    >>> type(a)
    <class '__main__.subDate'>			# Et voilà, j'ai bien un subDate
    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]

  19. #39
    Expert confirmé Avatar de papajoker
    Homme Profil pro
    Développeur Web
    Inscrit en
    Septembre 2013
    Messages
    2 104
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Nièvre (Bourgogne)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Septembre 2013
    Messages : 2 104
    Points : 4 454
    Points
    4 454
    Par défaut
    Pour recréer un "singledispatchmethod", je me suis amusé

    Note: pour amusement uniquement ! aucun intérêt de faire un code python pas standard Et pas d'intérêt d'apporter une couche supplémentaire qui va rendre python encore plus rapide.

    Reprend la syntaxe de singledispatchmethod avec "register", mais ici gère bien tous les paramètres et non que le premier
    On peut alors avoir plusieurs __init__() et donc ne pas passer par @classmethod (paramètres non nommés uniquement) Attention, nous sommes dans du non explicite donc pas une sauce python !

    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
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    class OverMethod:
     
        def __init__(self, func):
            #print("\nover init:", func.__name__, func)
            if not callable(func) and not hasattr(func, "__get__"):
                raise TypeError(f"{func!r} n'est pas une méthode")
            self.funcs = {}
            self.funcs["_"] = func
     
        def register(self, cls, method=None):
            """ nouvelle méthode avec signature différente """
            ann = getattr(cls, '__annotations__', {})
            if not ann:
                raise Exception("Types doivent être présents !")
            #print("Signature de la méthode:", ann.values())
            name = f"{'_'.join(a for a in ann.values())}"
            self.funcs[name] = cls
            #print("self.funcs:", self.funcs)
            return method
     
        def __get__(self, obj, cls=None):
            """ recherche méthode avec bonne signature """
            def _method(*args, **kwargs):
                name = f"{'_'.join(type(a).__name__ for a in args)}"
                # gérer kwargs trop compliqué ...
                if name in self.funcs:
                    if f := self.funcs[name]:
                        return f(obj, *args, **kwargs)
                    else:
                        raise Exception("?")
                else:
                    #print(f"# ({name}) n'existe pas pour {self.func.__name__}")
                    return self.funcs["_"](obj, *args, **kwargs)
            return _method
     
     
     
    class A:
        @OverMethod
        def __init__(self):
            print("\n#init defaut")
            self.name = "un test..."
     
        @__init__.register
        def _(self, name: str):
            print("\n#init custum")
            self.name = name
     
        @OverMethod
        def print(self, name: str, message='+'):
            print(f"{'defaut str':14} : {self.name} : {name} {message}")
     
        @print.register
        def _(self, name: int, message: str = '+'):
            print(f"{'int, str':14} : {self.name} : {name} {message}")
     
        @print.register
        def _(self, name: str, message: str = "+"):
            print(f"{'str, str':14} : {self.name} : {name} : {message}")
     
        @print.register
        def _(self, x: int):
            print(f"{'int':14} : {self.name} : {x}")
     
     
    a = A()
    a.print("un", "deux")
    a.print(name=1, message="deux")  #FIXME gere pas kwargs
    a.print(1, "deux")
    a.print(100)
    a.print("un")
    a.print([])  # si pas signature, prend @OverMethod
     
    b = A("autre")
    b.print([])
     
    try:
        c = A("autre", 8, 8, 9)
    except TypeError:
        print("Exception trop de paramètres")
    Citation Envoyé par popo Voir le message
    Du coup puisque python sait distinguer une variable statique d'une variable d'instance, pourquoi avoir besoin de classmethod ?
    ? Tu fais de l'objet ?

    L'énoncé de wiztricks était pourtant clair :
    Une static method python n'a d'accès qu'aux variables globales et aux paramètres passés.
    donc avec ta question, on doit transférer toutes nos variables d'instance en variables statiques ! Si j'ai des variables qui ne sont associées qu'aux classes, il va falloir les déclarer en dehors et avec des noms à rallonge rappel, il n'existe pas de variables de classe statique en python Ou, une variable de classe est en fait une variable "statique" dans une classe.

    Note: Dans un module (un objet), nous avons des variables statiques
    $moi= ( !== ) ? : ;

  20. #40
    Expert éminent
    Avatar de fred1599
    Homme Profil pro
    Lead Dev Python
    Inscrit en
    Juillet 2006
    Messages
    3 824
    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 824
    Points : 7 120
    Points
    7 120
    Par défaut
    Hello,

    Il y a beaucoup de branlettes dans tout ça, rien de clair et qui permet d'exprimer le besoin en POO d'utiliser @staticmethod ou @classmethod à part @wiztricks qui indique que c'est un choix de syntaxe parce-que ce qu'on veut c'est que ça marche et que si on en a besoin c'est qu'on sait ce qu'on fait peu importe si du point de vue POO c'est une bonne pratique ou non.

    Je vais donner le fond de ma pensée, car depuis des années j'ai déjà pas mal tranché sur le sujet.

    @staticmethod : Aucun intérêt ! Pourquoi j'aurai besoin d'une méthode si aucun changement d'état de l'objet est appliqué ? Pour moi l'utiliser est une erreur de conception du point de vue POO.

    @classmethod : Un seul intérêt à mon sens, modifier l'état des variables de classe qui s'appliquera sur l'ensemble des objets créés.

    C'est un peu des réponses sur vos expériences que j'attendais, pas des liens vers des sites qui rabâchent la même chose et surtout souvent très incompréhensibles et confus.
    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)

+ Répondre à la discussion
Cette discussion est résolue.
Page 2 sur 3 PremièrePremière 123 DernièreDernière

Discussions similaires

  1. [AC-2003] Demande d'aide sur la Méthode Setfocus
    Par gwenagan dans le forum Requêtes et SQL.
    Réponses: 7
    Dernier message: 14/12/2020, 15h56
  2. demande d'aide sur un diagramme de classe
    Par naderinfo dans le forum UML
    Réponses: 1
    Dernier message: 23/03/2013, 10h34
  3. [Débutant] demande d'aide sur richfaces
    Par scaryfan dans le forum JSF
    Réponses: 5
    Dernier message: 24/09/2009, 13h57
  4. [Débutant] Demande d'info sur OpenGL
    Par SkyDev dans le forum OpenGL
    Réponses: 2
    Dernier message: 01/03/2005, 23h58
  5. demande d'aide sur samba
    Par marcoss dans le forum Développement
    Réponses: 5
    Dernier message: 04/12/2003, 19h38

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