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 :

Surcharge méthode, parade ? [Python 3.X]


Sujet :

Python

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Novembre 2009
    Messages
    212
    Détails du profil
    Informations personnelles :
    Âge : 35
    Localisation : France

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

    Informations forums :
    Inscription : Novembre 2009
    Messages : 212
    Par défaut Surcharge méthode, parade ?
    Bonjour,

    Je viens initialement du monde cpp, qui me permettait d'utiliser la surcharge de méthode dans une classe, je suis donc assez débutante en python. Hors, ce matin, je code la même naturellement en python en me disant que "hum, pas de type vraiment défini, il va se comporter comment ? je ne le sens pas le truc ...". Au final, j'avais plutôt une bonne intuition puisqu'il semblerait que python ne l'autorise pas (ou du moins prend la dernière méthode du nom dans la classe)...
    Du coup me voilà dans le pétrin (ou presque), j'avais dans l'idée de faire deux méthodes :
    - une prenant un ndarray 3d
    - une prenant un ndarray 4d

    Je me dis qu'une parade serait de réunir les deux méthodes, avec un jolie/moche if ce type tu fais ça, if autre type tu fais ça sinon tu me lèves une belle erreur. D'ailleurs, est ce qu'on peut tester le type en py ? Sauf que, je trouve ça moche, très moche .... Quelle est la bonne pratique sur ce sujet selon vous ?

    Merci et bonne journée !

  2. #2
    Membre Expert
    Homme Profil pro
    Inscrit en
    Avril 2004
    Messages
    1 068
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 1 068
    Par défaut
    J'ai rien compris.

  3. #3
    Membre actif
    Homme Profil pro
    Amateur débutant
    Inscrit en
    Décembre 2019
    Messages
    88
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Amateur débutant

    Informations forums :
    Inscription : Décembre 2019
    Messages : 88
    Par défaut
    discution sur stackoverfolw .. juste au cas ou ca puisse aider.

  4. #4
    Membre Expert

    Homme Profil pro
    Ingénieur calcul scientifique
    Inscrit en
    Mars 2013
    Messages
    1 229
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur calcul scientifique

    Informations forums :
    Inscription : Mars 2013
    Messages : 1 229
    Par défaut
    Dans votre cas vous n'avez pas à faire un test "sale" sur le type attendu, puisque c'est un ndarray. Vous pouvez juste ajuster le comportement en testant l'attribut votre_array.ndim, qui vous renverra la dimension de votre array.

  5. #5
    Invité
    Invité(e)
    Par défaut
    Je pense que Wiz à tout dit, tout dépend de ton code, avec mon petit niveau je n'ai jamais entendu parler d'overloading avant aujourd'hui et ça ne m'a jamais dérangé.
    Je rajouterais même que savoir qu'il est possible d'avoir des fonctions qui portent le même nom mais qui font des trucs différents dans un même script, me choque !

    Une méthode qui va me valoir des coups de bâton, mais que j'utilise quand même c'est le try except :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    >>> class n:
    	t=5     
    >>> try:
    	n.o
    except AttributeError:
    	n.t
     
     
    5
    Si jamais tu ne connaissais pas...


  6. #6
    Membre Expert
    Avatar de Pyramidev
    Homme Profil pro
    Tech Lead
    Inscrit en
    Avril 2016
    Messages
    1 513
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Tech Lead

    Informations forums :
    Inscription : Avril 2016
    Messages : 1 513
    Par défaut
    Bonjour angioedema,

    Pour répondre à la question générale, en Python statiquement typé, depuis Python 3.8, la manière idiomatique de faire de la surcharge de méthode en fonction du type du paramètre qui suit self est d'utiliser functools.singledispatchmethod : https://docs.python.org/3/library/fu...dispatchmethod

    L'ancienne manière de faire était d'utiliser typing.overload : https://docs.python.org/3/library/ty...yping.overload
    (Cela dit, typing.overload reste utile dans d'autres cas.)

    Mais cela ne s'applique pas à ton exemple avec numpy.ndarray, car Python ne verra pas une différence de type entre un numpy.ndarray de dimension 3 et un numpy.ndarray de dimension 4.

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

    Citation Envoyé par angioedema Voir le message
    Quelle est la bonne pratique sur ce sujet selon vous ?
    Il n'y en a pas puisque Python n'en propose pas "de base".

    Et honnêtement, ça ne m'a jamais embêté plus que ça car on peut très bien faire 2 méthodes séparées, tester le type de l'argument (avec isinstance...), ... voire ne rien faire du tout car il y a des cas où l'algorithme ne change pas trop que le tableau soit 4D ou 3D.

    Ceux qui ne peuvent pas vivre sans peuvent évaluer des packages dans PyPI qui réalisent l'overloading.

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

  8. #8
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 835
    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 835
    Billets dans le blog
    1
    Par défaut
    Bonjour
    Citation Envoyé par angioedema Voir le message
    Au final, j'avais plutôt une bonne intuition puisqu'il semblerait que python ne l'autorise pas (ou du moins prend la dernière méthode du nom dans la classe)...
    Oui et non. Déjà dire que Python n'a pas de type vraiment défini est absolument faux! Python est un langage totalement typé. Sauf que le type est créé non pas avec la variable mais avec la valeur qu'on lui donne. a=5 donnera "a est un int et aura toutes les possibilités offertes aux int" mais a="toto" donnera "a est une string et aura toutes les possibilités offertes aux strings".
    Et cela n'interdit pas de forcer manuellement un type => a=float(5) donnera "a est un float et aura toutes les possibilités offertes aux floats".
    Petite parenthèse: Python3 a introduit les annotations en offrant la possibilité de spécifier le type attendu par la variable => a:int=5 ou même a:(int, float)=0.5. Malheureusement (ou heureusement cela dépend du point de vue de chacun) ces annotations ne sont que purement informatives et n'ont pour l'instant aucune obligation de correspondance concrète => a:int="toto" est accepté (ensuite en sera-t-il toujours ainsi dans le futur...?)

    Sinon effectivement Python n'autorise pas la surcharge de méthode puisque la surcharge au sens C++ se fait par la signature (la méthode attend un char vs la méthode attend un int) et que la fonction (ou la méthode) en Python n'a pas de signature typée (le paramètre prendra le type adéquat au moment où il recevra la valeur de l'argument passé). Fatalement avec deux définitions de la même méthode, la seconde écrase la première. On peut même se dire que Python pourrait prévenir (j'ai récemment trouvé deux méthodes identiques dans un de mes objets et je me dis qu'il pourrait y en avoir d'autres) mais tant pis (il existe cependant des vérificateurs tels que pylint et je suis en train de regarder s'il contient une option à ce sujet).

    Donc obligation de faire autrement. Mais Python t'offre en même temps la possibilité de faire autrement!!!
    Déjà il peut effectivement tester le type => if type(a) == int. Il peut même tester plusieurs types => if type(a) in (int, float). Et il offre même la fonction isinstance() qui non seulement sait reconnaitre un type mais sait aussi reconnaitre un héritage => if isinstance(a, (int, float)) fonctionnera même si "a" est un type spécifique qui hérite d'un int (ou d'un float).
    De plus un type étant un objet manipulable, rien ne t'interdit alors de créer une fonction dans laquelle tu passeras spécifiquement le type définissant son comportement attendu, type pouvant alors être évalué de façon directe
    Code python : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    def fct(n, tp):
    	if tp == str: print("string n: ", n)
    	if tp == int: print("int n: ", n)
    	if tp == float: print("float n: ", n)
    # fct()
     
    fct("hello", str)
    fct(5, int)
    fct(5.0, float)
    a=123
    fct(a, type(a))
    Tu peux même définir des fonctions spécifiques dans la fonction initiale...
    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
    def fct(n, tp):
    	def p_str(n): return "string n: {}".format(n)
    	def p_int(n): return "int n: {}".format(n)
    	def p_float(n): return "float n: {}".format(n)
    	if tp == str: print(p_str(n))
    	if tp == int: print(p_int(n))
    	if tp == float: print(p_float(n))
    # fct()
     
    fct("hello", str)
    fct(5, int)
    fct(5.0, float)
    a=123
    fct(a, type(a))
    ... ce qui peut être couplé à un dictionnaire de fonctions (ressemblant alors au pointeur de fonctions du C/C++)...

    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
    15
    16
    17
    def fct(n, tp):
    	def p_str(n): return "string n: {}".format(n)
    	def p_int(n): return "int n: {}".format(n)
    	def p_float(n): return "float n: {}".format(n)
    	ptF={
    		str : p_str,
    		int : p_int,
    		float : p_float,
    	}
    	print(ptF[tp](n))
    # fct()
     
    fct("hello", str)
    fct(5, int)
    fct(5.0, float)
    a=123
    fct(a, type(a))
    ... et finalement en arriver effectivement à utiliser directement le type du paramètre.
    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
    15
    16
    17
    def fct(n):
    	def p_str(n): return "string n: {}".format(n)
    	def p_int(n): return "int n: {}".format(n)
    	def p_float(n): return "float n: {}".format(n)
     
    	print(
    		{
    			str : p_str,
    			int : p_int,
    			float : p_float,
    		}[type(n)](n)
    	)
    # fct()
     
    fct("hello")
    fct(5)
    fct(5.0)

    C'est différent du C++ effectivement mais Python est différent du C++ (sinon ce ne serait pas Python mais C++ !!!) mais comme tu vois il offre quand-même des possibilités assez souples, possibilités qui peuvent même être "cachées" dans des décorateurs, c'est à dire des fonctions qui ont pour but d'encapsuler de façon invisible les fonctions de l'utilisateur dans une surcouche de traitement à faire en plus (ce que montrent les exemples de Pyramidev et wiztricks). Sinon l'autre solution plus basique est de définir des méthodes avec des noms spécifiques. Ensuite y a-t-il une meilleure façon qu'une autre ça c'est selon les opinions (et aussi les besoins) de chacun.
    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]

  9. #9
    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
    Citation Envoyé par angioedema Voir le message
    Du coup me voilà dans le pétrin (ou presque), j'avais dans l'idée de faire deux méthodes :
    - une prenant un ndarray 3d
    - une prenant un ndarray 4d

    Je me dis qu'une parade serait de réunir les deux méthodes, avec un jolie/moche if ce type tu fais ça, if autre type tu fais ça sinon tu me lèves une belle erreur. D'ailleurs, est ce qu'on peut tester le type en py ? Sauf que, je trouve ça moche, très moche .... Quelle est la bonne pratique sur ce sujet selon vous ?

    Merci et bonne journée !
    Un type ndarray 3d ou ndarray 4d aura le même type, ce n'est donc pas une comparaison de types, mais une vérification sur le nombre de dimensions de ton ndarray. Ça peut se faire avec numpy.size ou numpy.shape je ne connais pas assez numpy.

    On pourrait très bien s'imaginer que selon le nombre de dimensions, on appelle une méthode spécifique

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    def method(array):
        dimensions = np.size(array)
        function = functions[dimensions]
        return function(array)
    avec functions qui serait un dictionnaire

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    functions = {3: f3d, 4: f4d}
    Je pense que c'est indirectement une solution proposée par @wiztricks avec ses deux méthodes.

  10. #10
    Membre confirmé
    Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Novembre 2009
    Messages
    212
    Détails du profil
    Informations personnelles :
    Âge : 35
    Localisation : France

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

    Informations forums :
    Inscription : Novembre 2009
    Messages : 212
    Par défaut
    Merci pour l'ensemble de vos réponses !

    Je vais me permettre de répondre à certains points :
    - lorsque je parle de type, l'idée des dimensions étaient incluses, j'avoue m'être mal exprimé
    - la surcharge peut être utile pour la lisibilité du code - entre autre - même si elle n'est pas essentielle, ça reste mon point de vue de dev cpp



    Plus spécifiquement, je réponds à chacun (vous avez pris le temps, à moi de le prendre ) :
    @josmiley : je t'invite à regarder la surcharge de méthode, juste sur le principe, qui est beaucoup utilisé dans d'autres langages

    @wiztricks : Effectivement étant du cpp, j'ai foncé. Je ne dirais pas que je ne peux pas vivre sans, au contraire, si python ne le propose pas, je fais sans mais autant connaitre la bonne démarche

    @Jma06 : merci pour le lien, je n'y étais pas tombé dessus. Les réponses rejoignent ce que j'avais lu ce qui me rassure

    @lg_53 : mea culpa, je me suis mal exprimé comme expliqué plus haut, je pensais entre autre à la dimension

    @LeNarvalo : j'utilise bcp les try except quelque soit le langage effectivement. Pour l'overloading, dans mon utilisation, la méthode fait la même chose mais avec des paramètres d'entrée différente (car en cpp typage écrit oblige)

    @pyramidev : je ne connaissais pas functools, je regarde de ce pas pour la connaissance. Et effectivement, j'aurais du parler de méthode en donnant l'exemple des dims (car je ne connais que celui ci et étant débutante je ne connais pas les bonnes pratique) et non de type. Mais mon erreur me permet de connaitre ce type d'utilitaire grâce à toi, toujours bon à prendre

    @Sve@r : là aussi j'ai été un peu vite en disant que aucun type, effectivement non, j'entendais type vraiment défini comme en cpp. Après j'ai pu voir des codes avec le type attendu en Python, bonne pratique ou non ? Et l'ensemble de tes explications sont vraiment claire, top ! Et je te rejoints Python est différent du c++. Personnellement - attention je tends le - je préfère c++ . Mais là je n'ai pas le choix

    Merci encore pour l'ensemble de vos réponses, je passe le sujet en résolu

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

Discussions similaires

  1. Surcharger méthode async qui n'a pas besoin de "await"
    Par Ikit dans le forum Général Python
    Réponses: 1
    Dernier message: 14/04/2017, 15h57
  2. Surcharge méthode "magique" __sleep
    Par Atara dans le forum Langage
    Réponses: 1
    Dernier message: 11/05/2009, 13h43
  3. Surcharge méthode dispose()
    Par Bebert71 dans le forum NetBeans
    Réponses: 4
    Dernier message: 26/01/2008, 17h46
  4. [Custom Tags] Problème avec une surcharge de méthode
    Par Strab dans le forum Taglibs
    Réponses: 19
    Dernier message: 26/08/2005, 16h34
  5. Comment surcharger la méthode OnClose d'un TFrame ?
    Par sdebrois dans le forum Composants VCL
    Réponses: 2
    Dernier message: 17/01/2005, 20h57

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