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 :

Priorité des opérateurs surchargés dans un cas ambigu


Sujet :

Python

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2014
    Messages
    3
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 30
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mai 2014
    Messages : 3
    Par défaut Priorité des opérateurs surchargés dans un cas ambigu
    J'ai créé une classe Matrice et une classe Fraction qui gèrent chacune la surcharge des opérateurs qui leur sont compatibles.
    L'opérateur * est surchargé pour la classe Matrice par les deux méthodes __mul__et __rmul__.
    La première effectue le produit de deux matrices et lève une exception si le second argument n'est pas une matrice.
    La seconde permet de multiplier la matrice par un scalaire de type int ou Fraction.
    Seulement voilà si j'exécute : ma_fraction * ma_matrice ; ça déclenche Fraction.__mul__ et non Matrice.__rmul__ comme escompté. Evidemment Fraction.__mul__ n'est pas conçue pour recevoir une instance de Matrice donc plante.
    (Je précise que si j'exécute: ma_matrice.__rmul__(ma_fraction) ça marche parfaitement, c'est donc bien un problème de priorité)
    Comment faire pour établir une priorité entre les différentes surcharges de l'opérateur * dans ce cas ambigu? (il s'agit de deux classes qui ne sont pas liées par héritage)

    Merci d'avance pour vos réponses!

  2. #2
    Invité
    Invité(e)
    Par défaut
    Citation Envoyé par armapython Voir le message
    J'ai créé une classe Matrice et une classe Fraction qui gèrent chacune la surcharge des opérateurs qui leur sont compatibles.
    L'opérateur * est surchargé pour la classe Matrice par les deux méthodes __mul__et __rmul__.
    La première effectue le produit de deux matrices et lève une exception si le second argument n'est pas une matrice.
    La seconde permet de multiplier la matrice par un scalaire de type int ou Fraction.
    Seulement voilà si j'exécute : ma_fraction * ma_matrice ; ça déclenche Fraction.__mul__ et non Matrice.__rmul__ comme escompté. Evidemment Fraction.__mul__ n'est pas conçue pour recevoir une instance de Matrice donc plante.
    (Je précise que si j'exécute: ma_matrice.__rmul__(ma_fraction) ça marche parfaitement, c'est donc bien un problème de priorité)
    Comment faire pour établir une priorité entre les différentes surcharges de l'opérateur * dans ce cas ambigu? (il s'agit de deux classes qui ne sont pas liées par héritage)

    Merci d'avance pour vos réponses!
    Bonjour,

    l'interpréteur Python évalue l'opérateur * de gauche à droite e.g. dans a * b, c'est d'abord a qui est évalué, puis *, puis b et l'interpréteur remplace cette expression par a.__mul__(b)

    si l'opérateur * signifie multiplication pour les nombres et donc est commutatif pour les nombres, ce n'est pas le cas pour les objets.

    ainsi, lorsque vous écrivez ma_fraction * ma_matrice, vous écrivez en réalité ma_fraction.__mul__(ma_matrice).

    de même, lorsque vous écrivez ma_matrice * ma_fraction, vous écrivez en réalité ma_matrice.__mul__(ma_fraction).

    dans le cas des objets, l'opérateur * n'est pas commutatif.

    vous voyez comment tout cela fonctionne ?

    @+.

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

    Il faut faire comme çà:
    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
    >>> class A:
    ...     def __mul__(self, other):
    ...         print ('A mul')
    ...     def __rmul__(self, other):
    ...         print ('A rmul')
    ...
    >>> class B:
    ...     def __mul__(self, other):
    ...         if not isinstance(other, B):
    ...             print ('B mul route: ', end='')
    ...             return NotImplemented
    ...         print ('B mul')
    ...
    >>> a, b = A(), B()
    >>>
    >>> a * b
    A mul
    >>> b * a
    B mul route: A rmul
    >>> b * b
    B mul
    >>> a * a
    A mul
    >>>
    Dit autrement, b * a est d'abord évalué suivant b.__operator__(a).
    Le "return NotImplemented" force le passage par le __rmul__

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

  4. #4
    Invité
    Invité(e)
    Par défaut
    Citation Envoyé par wiztricks Voir le message
    Salut,
    Le "return NotImplemented" force le passage par le __rmul__

    - W
    je viens d'apprendre une chose intéressante, là.

    @+.

  5. #5
    Membre actif
    Homme Profil pro
    Inscrit en
    Février 2013
    Messages
    37
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Février 2013
    Messages : 37
    Par défaut
    Alors là je comprend pas ce qu'il se passe...

    Comment "return NotImplemented" 'force la passage par __rmul__', d'abord, et qu' est-ce qu'il se passe lors du print dans la méthode __mul__ de B (c'est quoi ce 'end' ?).

  6. #6
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 746
    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 746
    Par défaut
    Citation Envoyé par Delbor Voir le message
    Alors là je comprend pas ce qu'il se passe...

    Comment "return NotImplemented" 'force la passage par __rmul__', d'abord, et qu' est-ce qu'il se passe lors du print dans la méthode __mul__ de B (c'est quoi ce 'end' ?).
    C'est ce que dit la documentation: emulating-numeric-types
    Pour la commande print c'est ici.

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

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

Discussions similaires

  1. Priorité des opérateurs dans un IF
    Par gil38 dans le forum Fortran
    Réponses: 6
    Dernier message: 27/04/2011, 21h31
  2. priorité des opérateurs surchargés
    Par Heimdall dans le forum C++
    Réponses: 8
    Dernier message: 29/03/2011, 09h32
  3. Meilleure solution pour des unit tests? (dans mon cas)
    Par nicdo77 dans le forum Tests et Performance
    Réponses: 2
    Dernier message: 19/08/2007, 19h32
  4. Priorité des opérateurs
    Par neuromencien dans le forum Langage
    Réponses: 3
    Dernier message: 14/05/2007, 17h06
  5. Réponses: 3
    Dernier message: 31/08/2006, 10h39

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