La soustraction en python...

Bonsoir à tous,
je dispose en python d'une classe Complexe et j'aimerais implémenter la soustraction de deux complexes, ce problème d'apparence banale me tracasse tout de même.
Si j'ai deux complexes $z1$ et $z2$, $z1-z2$ fonctionne à merveille,
si j'ai un complexe $z$, $z-3$ ne pose aucun souci,
par contre je ne parviens pas à "calculer" $3-z$.

J'imagine que dans ce dernier cas, il va chercher la méthode __sub__ relative aux entiers et malgré mes tripatouillage avec "rsub" et "isinstance", je ne parviens pas à obtenir le résultat attendu.
D'avance merci de vos réponses.
F.

Réponses

  • malavita
    Modifié (November 2021)
    Tiens, il semble qu'on ne puisse plus éditer les messages...je vous prie donc de m'excuser des fautes de frappes du message précédent ;-) Je viens de voir la petite roue o:)
  • Donc, tu n'as pas créé une fonction du genre :   def MaSoustraction (a,b):
    Mais tu fais en sorte que le symbole $-$ appelle ta soustraction plutôt que la soustraction native, c'est ça ?

    Je connais très peu de choses sur Python, et je suis très curieux de savoir comment on fait ça !
    Tu me dis, j'oublie. Tu m'enseignes, je me souviens. Tu m'impliques, j'apprends. Benjamin Franklin
  • malavita
    Modifié (November 2021)
    class MesComplexes:
    def __init__(s,r,i=0):
    s.r = r
    s.i = i
    def __str__(s):
    return '(%g,%g)' % (s.r,s.i) # formatage "à la printf", vous pouvez utiliser toute autre méthode bien sûr
    def __add__(s,o): #"s+o" sera interprété comme s.__add__(o)
    if isinstance(o,(int,float)): o=MesComplexes(o)
    return MesComplexes(s.r+o.r,s.i+o.i)
    def __radd__(s,o): #si à "a+b" ne correspond pas de a.__add__(b), python essaiera b.__radd__(a)...
    return s+o #...éventuellement avec un autre __add__ ici s=b et o=a pour l'addition, cela se passe comme ça:
    On définit une classe complexe, puis on redéfinit l'addition pour les éléments de cette classe. Bien évidemment pour bien faire, il faudrait que cette addition puisse comprendre des choses du genre $(1+i)+2$ et $2+(3+i)$.
    La seconde somme est traitée par "isinstance" de la méthode $__add__$. La méthode $__raad__$ est utilisée en cas d'échec de la première méthode, elle essaye de faire $o+s$ à la place de $s+o$... c'est en tout cas ce que j'ai compris ;-). Dans ce cas, il est très facile d'utiliser la méthode $__radd__$ car l'addition est commutative.
    J'ai bricolé autant que j'ai pu pour la soustraction, mais je ne trouve toujours pas de solutions...
    Bonne soirée.
    F.
    PS. Le code Python est indenté dans le message original, mais l'indentation disparait lors de la mise en forme du message... Et vu que des balises <br> apparaissent, j'imagine qu'il y a un petit souci qui n'est pas de mon fait ;-)
  • MrJ
    MrJ
    Modifié (November 2021)
    N’est-il pas possible dans ta fonction différence de définir l’opposée de o (quitte à traiter différent cas selon son type) puis d’utiliser tes fonctions d’additions?
  • raoul.S
    Modifié (November 2021)
    @malavita il faut que tu implémentes la méthode __rsub__ (comme tu l'as fait pour __radd__) et ça marchera.

  • malavita
    Modifié (November 2021)
    Bonsoir Raoul,
    c'est bien ce que j'essaye de faire mais je me retrouve avec des choses du genre $3-(1+i)=-2+i$.
    Si j'ai bien compris, la méthode $__rsub__$ essaye juste de permuter les arguments et de voir si elle obtient un résultat, si oui elle donne ce résultat.
    A+
    F
  • Essaie avec cette méthode __rsub__ :

    def __rsub__(s,o):
        if isinstance(o,(int,float)):
            o=MesComplexes(o)
        return MesComplexes(-s.r+o.r,-s.i+o.i)
  • As-tu défini la méthode __neg__ ?
    Algebraic symbols are used when you do not know what you are talking about.
            -- Schnoebelen, Philippe
  • malavita
    Modifié (November 2021)
    Bonjour à tous,
    effectivement la méthode de Raoul fonctionne.
    Une autre qui semble donner le bon résultat est :
     def __rsub__(s,o):
    return -1*(s-o)
    Si j'ai bien compris, si j'essaye de calculer s-o :
    • dans un premier temps python essaye de calculer $s-o=sub(s,o)$
    • si cela ne fonctionne pas, il essaye de calculer $rsub(s,o)=sub(o,s)$ le résultat est alors noté $s-o$ et vaut $o-s$
    Pour Nicolas, si la méthode neg est définie j'imagine qu'un $return -s+o$ doit convenir ?
    Bon dimanche
    F.
  • malavita
    Modifié (November 2021)
    Re bonjour,
    sur le même sujet je dispose d'une classe point dans laquelle j'aimerais définir une fonction plot qui affiche un point donné. J'ai donc défini dans ma classe point la fonction suivante qui fonctionne correctement.
     def plot(self,color='red'):
    plt.plot([self.x],[self.y],'bo')
    Pour appeler cette fonction, j'utilise $Point.plot(M)$, cette fonction appelle la fonction plot de la classe Point et affiche le résultat. Est-il possible de faire en sorte qu'une fonction similaire puisse être appelée avec une commande du type $M.plot()$ ? J'ai bricolé des $def __plot__$ mais cela ne donne rien de bon.
    Bonne journée.
    F.
  • nicolas.patrois
    Modifié (November 2021)
    Pour __rsub__, la réponse est ici.
    Si ta méthode st définie dans ta classe, tu l’utilises comme tu voudrais le faire : si M est une instance de la classe Point et si plot est une méthode de la classe, tu tapes M.plot().
    Algebraic symbols are used when you do not know what you are talking about.
            -- Schnoebelen, Philippe
  • malavita
    Modifié (November 2021)
    Bonjour Nicolas et merci de ta réponse rapide,
    donc si j'ai bien compris si M est une instance de la classe Point les commandes $M.plot()$ et $Point.plot(M)$ sont équivalentes ?
    Lorsqu'on essaye de calculer a+b, python va chercher dans ses diverses additions s'il y en a une qui correspond au type de a et au type de b, si ce n'est pas le cas il renvoie un "not implemented" et essaye de calculer b+a avec la méthode radd ?
    Bonne journée.
    F.
  • Normalement, pour utiliser Point.plot, il faut la définir en dehors de la classe. Si tu la définis dans la classe, c’est une méthose utilisable avec les instances.
    Si tu veux utiliser Point.plot(M), il faut définir Point.plot, par exemple comme ça :
    def Point.plot(M):
    M.plot()
    Je n’ai pas essayé mais ça devrait marcher.
    Tu pourrais même le faire systématiquement pour toutes les méthodes en parcourant leur liste avec dir() puis en utilisant setattr.
    Algebraic symbols are used when you do not know what you are talking about.
            -- Schnoebelen, Philippe
  • malavita
    Modifié (November 2021)
    Bonjour Nicolas,
    apparemment si je définis ma fonction plot dans ma classe point, les deux commandes Point.plot(M) et M.plot() semblent fonctionner de façon identique.
    En tout cas merci pour tes réponses et bon dimanche.
    F.
Connectez-vous ou Inscrivez-vous pour répondre.