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 :

Python paresseux !


Sujet :

Python

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Rédacteur
    Avatar de Zavonen
    Profil pro
    Inscrit en
    Novembre 2006
    Messages
    1 772
    Détails du profil
    Informations personnelles :
    Âge : 77
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 1 772
    Par défaut Python paresseux !
    'Lazzy' est un mot à la mode. La 'lazzy evaluation' c'est 'fashion'.
    Python n'est jamais en retard, en voici la preuve.
    Dans un passé proche on ne disposait pas du type 'rationnel' en standard (il paraît que c'est fait depuis la version 2.6, mais j'attends encore un peu parce que la plupart des biblios sont soit incompatibles soit non à jour quoiqu'on dise...).
    Quoiqu'il en soit j'ai relevé mes manches pour 'palucher' une classe des rationnels.
    Ca donne à peu près ça. Je l'ai fait à l'instinct et par la suite, quand j'ai vu des propositions tierces, elles ressemblaient comme deux gouttes d'eau à la mienne. Comme quoi, dans ce cas d'école il n'y a pas 36 façons de faire. Bref ça donne ça ...
    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
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    # -*- coding: utf-8 -*-
    from math import *
     
    # un module de modélisation des nombres rationnels
     
    # pgcd de deux entiers positifs
    #suivant l'algorithme d'Euclide
    def pgcd(x,y):
        if(x==0 or y==0):
            return 1
        if (y%x==0):
            return x
        else:
            return pgcd(y%x,x)
        return
     
    #*****************classe Rationnel*********************************
    class Rationnel:
     
        #simplification des fractions
        def normalise(self):
            g = pgcd(abs(self.num), abs(self.den))
            self.num = self.num / g
            self.den = self.den / g
            if(self.num*self.den<0):
                if self.den<0:
                    self.den=-self.den
                    self.num=-self.num
            else:
                if self.den <0:
                    self.den=-self.den
                    self.num=-self.num
            return
     
        def __init__(self, num, den = 1):  # Constructeur
            if den == 0:
                raise ZeroDivisionError, 'denominateur nul'
            else:
                self.num=num
                self.den=den
                self.normalise()
            return
        #teste si la fraction est entière
        def entier(self):
            return self.num%self.den==0
        #teste si nulle
        def nul (self):
            return self.num==0
     
        """Les opérations binaires"""
        def __add__(self, other): #addition
            n=self.num*other.den+other.num*self.den
            d=self.den*other.den
            return Rationnel(n,d)
        def __rmul__(self,other): #multiplication
            n=self.num*other.num
            d=self.den*other.den
            return Rationnel(n,d)
        def __sub__(self, other): #soustraction
            n=self.num*other.den-other.num*self.den
            d=self.den*other.den
            return Rationnel(n,d)
        def __div__(self,other): #division
            if other.nul():
                raise ZeroDivisionError, 'diviseur nul'
            else:
                n=self.num*other.den
                d=self.den*other.num
                return Rationnel(n,d)
            return
        """opérateurs unaires"""
        def __neg__(self): #opposé
            return Rationnel(-self.num,self.den)
        def __invert__(self):
            if self.nul(): #inverse
                raise ZeroDivisionError, 'diviseur nul'
            else:
                return Rationnel (self.den,self.num)
            return
        def __pow__(self,n):
            if n==0:
                return Rationnel(1,1)
            elif n>0:
                return Rationnel (self.num**n,self.den**n)
            else:
                if self.nul():
                    raise ZeroDivisionError, 'puissance negative d\' nul'
                else:
                    return Rationnel(self.den**(-n),self.num**(-n))
            return
     
        """Les comparaisons"""
        def __eq__(self,other):
           return self.num*other.den==self.den*other.num
        def __lt__(self,other):
            return self.num*other.den<self.den*other.num
        def __le__(self,other):
            return self.num*other.den<=self.den*other.num
        def __gt__(self,other):
            return self.num*other.den>self.den*other.num
        def __ge__(self,other):
            return self.num*other.den>=self.den*other.num
        def __ne__(self,other):
           return self.num*other.den!=self.den*other.num
     
        # pour voir une fraction sur la console appelée par print
        def __str__(self):
            if self.entier():
                return str(self.num)
            else:
                return str(self.num)+'/'+str(self.den)
    #************************fin de la définition**********************
    Il y a une bizarrerie...
    L'opérateur de multiplication est défini par une surcharge de __rmul__ et non de __mul__ (en gros pour ceux qui l'ignorent rmul c'est quand le self est l'opérande de droite.
    Si vous surchargez __mul__ au lieu de __rmul__ cela marche aussi bien.
    Venons en au fait. Mon but est de développer un module d'algèbre linéaire sur le corps Q (c'est d'ailleurs chose faite maintenant).
    Alors à partir du type rationnel il faut développer les vecteurs à composantes rationnelles, les matrices à coeffs rat. etc, etc..
    Commençons par les vecteurs.
    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
    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
    # -*- coding: utf-8 -*-
     
    from rationnels import *
    class VecteurQn:
        """modélisation des vecteurs à n dimensions rationnelles"""
        def __init__(self,L):
            """constructeur"""
            self.V=L
            self.n=len(L)
        def __str__(self):
            """resprésentation externe print, etc..."""
            L=[str(x) for x in self.V]
            return '('+ ",".join(L)+')'
        def nul(self):
            """test de nullité"""
            return all([x.nul() for x in self.V])
        def __add__(self,other):
            """addition des vecteurs"""
            if self.n!=other.n:
                raise 'size: ' 'Tailles non concordantes'
            else:
                L=[self.V[i]+other.V[i] for i in range(0,self.n)]
                return VecteurQn(L)
        def __neg__(self):
            """opposé d'un vecteur"""
            return VecteurQn([-x for x in self.V])
        def __sub__(self,other):
            """différence de deux vecteurs"""
            return self+(-other)
        def __rmul__(self,k):
            """ produit par un scalaire rationnel"""
            L=[k*x for x in self.V]
            return VecteurQn(L)
     
    def main():
        """test de la classe ci-dessus"""
        half=Rationnel(1,2)
        third=Rationnel(1,3)
        one=Rationnel(1)
        L=[one,half, third]
        V1=VecteurQn(L)
        V2=V1
        print V1
        print V2
        print V1+V2
        print -V1
        V3=V1-V2
        print V3
        print V3.nul()
        V4=half*V1
        print V4
        print V4.nul()
        return
     
    if __name__=='__main__':
        main()
    Il faut définir le produit d'un vecteur par un scalaire et là ON N'A PAS LE CHOIX ! c'est bien __rmul__ qu'il faut surcharger.
    Que se passe-t-il si on a surchargé __mul__ dans la classe Rationnel ?
    Si je veux calculer (1/2)V il faudra écrire quelque chose comme :
    Un_demi (bien frais) = Rationnel(1,2)
    W=Un_demi*V
    Et là notre Python paresseux va refuser avec un message abscons.
    La raison !...
    Il veut évaluer un produit a * b où a est rationnel alors il va chercher la surcharge de __mul__ dans la classe correspondante et il trouve que comme le second facteur n'est pas du type rationnel il ne peut pas faire le travail, et puis il va se coucher.
    S'il n'était pas paresseux avant d'abandonner si rapidement il irait jeter un coup d'oeil sur l'opérande de droite et voir que pour sa classe il y a une surcharge de __rmul__.
    Python a encore beaucoup à apprendre de C++, cela ne pourrait arriver en C++ où toutes les possibilités sont testées et les ambiguïtés mise ne relief quand il y en a.
    Est-ce que j'ai bien compris?
    Ce qu'on trouve est plus important que ce qu'on cherche.
    Maths de base pour les nuls (et les autres...)

  2. #2
    Expert confirmé
    Avatar de tyrtamos
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2007
    Messages
    4 486
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2007
    Messages : 4 486
    Billets dans le blog
    6
    Par défaut
    Bonjour,

    Je ne suis pas un grand spécialiste de ces questions, mais il me semble que quand __mul__ ne s'applique pas, il doit renvoyer NotImplemented, et python passe alors la main à __rmul__. Donc, dans ton cas, il faut surcharger les 2 et définir quand l'un ou l'autre s'applique selon le pb que tu veux résoudre.

    http://docs.python.org/reference/dat...object.__mul__

    Tyrtamos

  3. #3
    Rédacteur
    Avatar de Zavonen
    Profil pro
    Inscrit en
    Novembre 2006
    Messages
    1 772
    Détails du profil
    Informations personnelles :
    Âge : 77
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 1 772
    Par défaut
    Merci Tyrtamos pour ta réponse,
    Je vais regarder ça dès que j'ai un moment.
    Ce qu'on trouve est plus important que ce qu'on cherche.
    Maths de base pour les nuls (et les autres...)

  4. #4
    Rédacteur
    Avatar de Zavonen
    Profil pro
    Inscrit en
    Novembre 2006
    Messages
    1 772
    Détails du profil
    Informations personnelles :
    Âge : 77
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 1 772
    Par défaut
    Etonnant !
    J'ai donc surchargé les deux opérateurs __mul__ et __rmul__ dans la classe Rationnel, avec des définitions différentes (juste pour voir).
    Normalement il y a ambiguïté et le compilateur devrait le remarquer, mais non... il prend par défaut la surcharge de __mul__ et pas l'autre.
    Cette remarque est très intéressante mais elle semble confirmer le fait que Python est vraiment suffisamment fainéant pour ne pas aller voir qu'existent des surcharges contradictoires.
    Pour ce qui concerne mon problème cela ne change rien; je suis obligé de surcharger__rmul__ de toutes façons donc la surchage de __mul__ n'apporte rien qu'une complication supplémentaire avec à la clé la certitude d'avoir des bugs dans une version future (4.5 ???) quand notre BDFL se rendra compte qu'il y a là un sérieux problème.
    Ce qu'on trouve est plus important que ce qu'on cherche.
    Maths de base pour les nuls (et les autres...)

  5. #5
    Membre chevronné Avatar de dapounet
    Profil pro
    Étudiant
    Inscrit en
    Juillet 2007
    Messages
    469
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juillet 2007
    Messages : 469
    Par défaut
    Bonjour,

    Citation Envoyé par Zavonen Voir le message
    Etonnant !
    J'ai donc surchargé les deux opérateurs __mul__ et __rmul__ dans la classe Rationnel, avec des définitions différentes (juste pour voir).
    Normalement il y a ambiguïté et le compilateur devrait le remarquer, mais non... il prend par défaut la surcharge de __mul__ et pas l'autre.
    Cette remarque est très intéressante mais elle semble confirmer le fait que Python est vraiment suffisamment fainéant pour ne pas aller voir qu'existent des surcharges contradictoires.
    Pour ce qui concerne mon problème cela ne change rien; je suis obligé de surcharger__rmul__ de toutes façons donc la surchage de __mul__ n'apporte rien qu'une complication supplémentaire avec à la clé la certitude d'avoir des bugs dans une version future (4.5 ???) quand notre BDFL se rendra compte qu'il y a là un sérieux problème.
    Il n'y a pas de surcharge de fonction en Python (quand on redéfinit une fonction, elle écrase simplement la précédente).
    Ce n'est pas peut-être qu'une apparence, mais quand je te lis j'ai l'impression que tu cherches plus à dénigrer Python qu'à résoudre un problème.
    Personnellement je n'ai pas compris ton problème (je ne vois pas le rapport avec l'évaluation paresseuse, par exemple).

  6. #6
    Rédacteur
    Avatar de Zavonen
    Profil pro
    Inscrit en
    Novembre 2006
    Messages
    1 772
    Détails du profil
    Informations personnelles :
    Âge : 77
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 1 772
    Par défaut
    je ne vois pas le rapport avec l'évaluation paresseuse, par exemple
    Il n'y a AUCUN rapport avec l'évaluation paresseuse.
    Et moi je vois qu'on ne rigole pas sur ce forum. J'en tiendrai compte désormais...
    j'ai l'impression que tu cherches plus à dénigrer Python qu'à résoudre un problème
    Si Python ne me plaisait pas, je ne perdrais pas mon temps à pleurnicher ici, je choisirai un autre langage, point final !
    Je CROIS simplement avoir mis le doigt sur une faiblesse du langage (qui a beaucoup plus de qualités que de défauts). Et je demande, à tout hasard, si quelqu'un partage mes conclusions, a rencontré des situations semblebles ou peut me proposer quelque chose de plus propre qu'une solution artificielle consistant à surcharger un opérateur 'cousin'.
    Par ailleurs si tu ne t'étonnes pas que puissent coexister deux surcharges contradictoires, et bien ... tant mieux pour toi.
    Ce qu'on trouve est plus important que ce qu'on cherche.
    Maths de base pour les nuls (et les autres...)

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

Discussions similaires

  1. [langage] traduction d'un fonction python en perl
    Par ay_pepito dans le forum Langage
    Réponses: 3
    Dernier message: 04/12/2007, 15h06
  2. CORBA & PYTHON
    Par stan91stan dans le forum CORBA
    Réponses: 5
    Dernier message: 10/06/2004, 12h32
  3. module .so pour python... ?!
    Par totoetlititi dans le forum Langages de programmation
    Réponses: 2
    Dernier message: 09/03/2004, 14h51
  4. [Lien]erreur dans mon programme python
    Par durnambule dans le forum Général Python
    Réponses: 11
    Dernier message: 29/01/2004, 14h59

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