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 :

erreur sur un exercice d'apprentissage [Python 3.X]


Sujet :

Python

  1. #1
    Membre à l'essai
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juillet 2009
    Messages
    9
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loiret (Centre)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Juillet 2009
    Messages : 9
    Points : 11
    Points
    11
    Par défaut erreur sur un exercice d'apprentissage
    Bonjour,

    J'essaie de faire un exercice pour mieux apprendre l'héritage de classe et je suis en but avec le problème suivant :
    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
     
    class MyList (list):
        def __init__ (self, args):
            self.ml = list (args)
     
        def __add__(self, args):
            #print ('overload add')
            if type (args) == list ():
                return MyList (self.ml [:] + args)
            else:
                return MyList (self.ml [:] + list (args))
     
        def __getattr__(self, name):
            #print ('attribute fetch')
            return MyList (getattr(self.ml, name))
        def __getitem__(self, offset):
            #print ('attribute fetch item')
            return self.ml [offset]
        def __repr__(self):
            return repr (self.ml)
     
    class MyListSub (MyList):
        numCall = 0
     
        def __init__ (self, args):
            MyListSub.numCall += 1
            self.sCall = 0
            print ('MyListSub, num call: %s' % self.numCall)
            return MyList.__init__ (self, args)
     
        def __add__ (self, args):
            self.sCall += 1
            print ('add of MyListSub, num call: %s' % self.sCall)
            return MyList.__add__(self, args)
     
        def stats (self):
            return self.numCall, self.sCall
     
    if __name__ == '__main__':
        a = MyListSub ('test')
        a = a + 'other'
        b = MyListSub ('spam')
        b = b + 'add'
        b = b + 'bacon'
        print (a, b)
        print (a.stats ())
        print (b.stats ())
    Lorsque le code exécute la méthode "stats", j'ai le message d'erreur suivant :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    Traceback (most recent call last):
      File "partIVExercises.py", line 77, in <module>
        print (a.stats ())
      File "partIVExercises.py", line 45, in __getattr__
        return MyList (getattr(self.ml, name))
    AttributeError: 'list' object has no attribute 'stats'
    J'ai essayé de surcharger la méthode getattr, mais ça n'a pas fonctionné.

    Quelqu'un aurait une idée où est mon erreur?

    Merci d'avance

  2. #2
    Expert éminent

    Homme Profil pro
    Inscrit en
    Octobre 2008
    Messages
    4 300
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Octobre 2008
    Messages : 4 300
    Points : 6 780
    Points
    6 780
    Par défaut
    Salut,

    Ce genre de choses demande un peu plus de précautions, tes
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
        def __getattr__(self, name):
            #print ('attribute fetch')
            return MyList (getattr(self.ml, name))
        def __getitem__(self, offset):
            #print ('attribute fetch item')
            return self.ml [offset]
        def __repr__(self):
            return repr (self.ml)
    entrainent d'inévitables RuntimeError: maximum recursion depth exceeded while calling a Python object

    D'autre part, pourquoi crées-tu une liste "self.ml" en attribut de ton instance ?
    self est la liste.

    Ensuite il ne faut pas surcharger une méthode de la classe uniquement pour l'appeler. Le __add__ de MyListSub ne fait rien de différent de celui de MyList

    La transformation d'objets t'échappe totalement avec ce code, si on rajoute quelques print pour voir:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    ...
        b = MyListSub ('spam')
        print(b)
        b = b + 'add'
        print(b)
        b = b + 'bacon'
        print (a, b)
    ça donne:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    MyListSub, num call: 1
    <MyList instance at 160473692>
    ['s', 'p', 'a', 'm', 'add']
    Traceback (most recent call last):
      File "subclass.py", line 49, in <module>
        b = b + 'bacon'
    TypeError: can only concatenate list (not "str") to list
    Un manière de corriger ç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
     
    class MyList (list):
        def __init__ (self, args):
            if isinstance(args, (list, tuple)):
                self.extend(args)
            else:
                self.append(args)
     
        def __add__(self, args):
            l = self[:]
            if isinstance(args, (list, tuple)):
                l.extend(args)
            else:
                l.append(args)
            return l
     
        def __repr__(self):
            return '<MyList instance at %s>' % id(self)
            # Autre possibilité
            return str(self[:])
     
    class MyListSub (MyList):
        numCall = 0
        def __init__ (self, args):
            super(MyListSub, self).__init__(args)
            self.numCall += 1
            self.sCall = 0
            # Erreur: __init__ ne doit rien retourner !!
            #return MyList.__init__ (self, args)
     
        def stats (self):
            return self.numCall, self.sCall
     
    if __name__ == '__main__':
        ml = MyList(('first', 'second'))
        print(ml)
        print(ml + 'third')
        a = MyListSub('test')
        a + 'other'
        b = MyListSub ('spam')
        print(b)
        b + 'add'
        print(b)
        b + 'bacon'
        print (a, b)
        print (a.stats ())
        print (b.stats ())

  3. #3
    Membre à l'essai
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juillet 2009
    Messages
    9
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loiret (Centre)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Juillet 2009
    Messages : 9
    Points : 11
    Points
    11
    Par défaut
    Bonjour,

    Merci pour la réponse.

    Finalement, j'ai réussi à corriger le code (avec peine et misère), bref, le commun de tout débutant.

    Il y avait plusieurs petites erreurs dans mon code qui, après 2h de recul et votre réponse, m'a permis de le corriger.

    En fait, là où je n'arrivais pas a comprendre l'erreur était le fait que je perdais systématiquement la méthode "stats" durant l'exécution du code. En fait, cela était tout à fait normal parce que la surcharge que j'ai fait sur le __add__ retournais une instance de classe "MyList" plutôt que "MyListSub", d'où l'explication de la méthode qui disparaissait.

    J'imagine que mon code contient encore des erreurs, mais ça m'a permis d'assimiler certaines notions.

    Voici la nouvelle mouture :
    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
     
    class MyList ():
        def __init__ (self, args):
            self.ml = list (args)
     
        def __add__(self, args):
            #print ('overload add')
            if type (args) == list ():
                return MyList (self.ml + args)
            else:
                return MyList (self.ml + list (args))
     
        def __getitem__(self, offset):
            #print ('attribute fetch item')
            return self.ml [offset]
        def __repr__(self):
            return repr (self.ml)
     
    class MyListSub (MyList):
        numCall = 0
     
        def __init__ (self, args):
            MyListSub.numCall += 1
            self.sCall = 0
            #print ('MyListSub, num call: %s' % self.numCall)
            MyList.__init__ (self, args)
     
        def __add__ (self, args):
            self.sCall += 1
            #print ('add of MyListSub, num call: %s' % self.sCall)
            return MyListSub (MyList.__add__(self, args))
     
        def stats (self):
            #repr ("instance calls: %s; method calls: %s" % (MyListSub.numCall, self.sCall))
            return MyListSub.numCall, self.sCall
     
    def myListExec ():
        a = MyListSub ('test')
        d = a + 'other'
        b = MyListSub ('spam')
        e = b + 'add'
        f = b + 'bacon'
        print (a, b)
        print (a.stats ())
        print (b.stats ())
        print (sorted (a.ml))

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

Discussions similaires

  1. erreurs de compilation sur des exercices
    Par isabelle94 dans le forum Débuter
    Réponses: 8
    Dernier message: 14/12/2012, 16h56
  2. Erreur de paie sur mon contrat d'apprentissage ?!
    Par bobinouze dans le forum Paie
    Réponses: 3
    Dernier message: 03/02/2010, 16h18
  3. [VBS] Erreur sur "AddWindowsPrinterConnection"
    Par Admin dans le forum VBScript
    Réponses: 5
    Dernier message: 27/03/2004, 16h15
  4. []Erreur sur second emploi collection binding
    Par jacma dans le forum VB 6 et antérieur
    Réponses: 2
    Dernier message: 08/03/2004, 18h02
  5. Erreur sur le TNSListener après installation de 9iAS
    Par Patmane dans le forum Installation
    Réponses: 4
    Dernier message: 04/02/2004, 11h16

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