angry Héritage simple et variable locale

Document Actions
Réponses: 5   Visites: 0
Up one level
Vous devez être un membre enregistré pour contribuer sur ce forum. Inscrivez-vous maintenant

angry Héritage simple et variable locale

Posté par breizhgatch le 12/07/2010 15:49
Bonjour,

Allo Houston, j'ai un problème!

Une classe B hérite de A qui ne contient qu'un attribut: une liste
Une classe C héritant également de A crée une instance de B dans son constructeur.

voici mon code:

code:
class A():
    l =[]
    def __init__(self):
        pass
    
class B(A):
    def __init__(self):
        A.__init__(self)
        self.l.append('b')

class C(A):
    def __init__(self):
        A.__init__(self)
        print 'xxx', ''.join(self.l)
        b = B()
        print 'xxx', ''.join(self.l)
        self.l.append(''.join(b.l))
        self.l.append('d')

if __name__ == '__main__':
    objC = C()
    print "objC: %s" % (''.join(objC.l))


En sortie , j'obtiens:
code:
xxx 
xxx b
objC: bbd


...alors que je m'attendais à avoir:
code:
xxx 
xxx 
objC: bd


Pourquoi la création de l'instance b vient marcher sur les plate-bandes de l'instance de C ???
Please, aidez-moi à comprendre

Re: Héritage simple et variable locale

Posté par benoit.intrw le 13/07/2010 11:03
Bonjour,

l étant déclaré en dehors de l'__init__ de A, c'est une variable de classe.
Dans l'__init__ de B c'est à ce même et unique attribut que tu ajoute 'b'.

J'ai ajouté des print aux tiens. AU #3 on voit qu'après instanciation de b l contient 'b'.

J'ai ajouté à la fin un print de A().l pour confirmer.

code:
class A(object):
    l =[]
    def __init__(self):
        pass
    
class B(A):
    def __init__(self):
        A.__init__(self)
        self.l.append('b')

class C(A):
    def __init__(self):
        print('#1 l = %s' % repr(self.l)) #[]
        A.__init__(self)
        print('#2 l = %s' % repr(self.l)) #[]
        print 'xxx', ''.join(self.l)
        b = B()
        print('#3 l = %s' % repr(self.l)) #['b']
        print 'xxx', ''.join(self.l)
        print('#4 l = %s' % repr(self.l)) #['b']
        self.l.append(''.join(b.l))
        print('#5 l = %s' % repr(self.l)) #['b', 'b']
        self.l.append('d')
        print('#6 l = %s' % repr(self.l)) #['b', 'b', 'd']

if __name__ == '__main__':
    objC = C()
    print "objC: %s" % (''.join(objC.l))
    print(repr(A().l)) #['b', 'b', 'd']


Benoît

Re: Héritage simple et variable locale

Posté par breizhgatch le 13/07/2010 15:13
Merci Benoît pour ta réponse rapide.

C'est justement là mon probleme, au #3... Pour faire simple, pourquoi c.l = b.l alors que elles sont bien distinctes, excepté qu'elles héritent toutes les 2 de la meme classe (A)?

(ca doit être un problème de compréhension du fonctionnement de python... oui, je sais, je viens du monde c++/c#... ;))

Re: Héritage simple et variable locale

Posté par alexg le 16/07/2010 16:21
Hello, je réponds peut être tard, mais ce que te dit Benoit et qui est important c'est que "l" tel que tu l'as définis est une *variable de classe*.

Souvent on voit des choses comme

code:
class A:
   l = 3


En fait dès que tu modifie l dans une instance de A, tu n'as pas de problème car l est dans ce cas **immuable** donc pour le modifier tu feras forcément une affectation :
code:
self.l = un_autre_truc


Dans ton cas tu définis

code:
class A:
   l =[code]
[/code]
et ensuite[code]self.l.append('bidule')[/code]donc on a self.l qui est en fait A.l et ceci que tu sois dans une instance de C ou B et quelque soit l'instance. (c'est ce qu'on appelle une variable de classe)

La bonne manière de faire c'est d'initialiser ta liste dans l' __init__ de A.

[code]
class A
  def __init__(self):
    A.l =[code]
[/code]

Le fait d'initialiser la variable dans la classe fonctionne est un raccourci à n'utiliser que pour les valeurs immuables ![/code]

angry Re: Héritage simple et variable locale

Posté par alexg le 16/07/2010 16:23
grumph ça m'apprendra à pas utiliser la prévisualisation jusqu'au bout

Re: Héritage simple et variable locale

Posté par breizhgatch le 19/07/2010 15:30
hello tous, et merci pour vos explications, c bon tout me semble plus limpide maintenant. je viens de saisir la différence entre variable de classe et variable d'instance en python! oui, en le déplacant dans l'__init__ (donc une variable d'instance), j'ai bien le comportement attendu!

Python.org : Le site officiel du langage Python.
Zope.org : Le site web officiel de Zope.
Daily Python-URL : Actus de l'univers Python.
Tribute to Zyons : Zyons notre ami et membre fondateur de l'Afpy, nous quittait en 2005.