2011-01-13 3 views
3

Warum gibt c.print_a() 'B' aus?Mehrfaches Vererbungsproblem in Python!

class A(object): 
    def __init__(self): 
     self.some_name = 'A' 

    def print_a(self): 
     print self.some_name 

class B(object): 
    def __init__(self): 
     self.some_name = 'B' 

    def print_b(self): 
     print self.some_name 

class C(A, B): 
    def __init__(self): 
     A.__init__(self) 
     B.__init__(self) 

if __name__ == '__main__': 
    c = C() 
    c.print_a() 

class A(object): 
    def __init__(self, some_name='A'): 
     self.some_name = some_name 

    def print_a(self): 
     print self.some_name 

class B(object): 
    def __init__(self, some_name='B'): 
     self.some_name = some_name 

    def print_b(self): 
     print self.some_name 

class C(A, B): 
    def __init__(self): 
     A.__init__(self, some_name='AAAAA') 
     B.__init__(self, some_name='BBBBB') 

if __name__ == '__main__': 
    c = C() 
    c.print_a() 
+0

Vielen Dank für Ihre Bearbeitung! – Suge

+0

Lassen Sie uns versuchen zu verdeutlichen: Sie wollen, dass C Namen für einige Objekte der Typen A und B setzt und später beim Aufruf einiger print_a und print_b Funktionen diese Namen zurückbekommt? – kriss

+0

Ja! Warum konnte ich den Code nicht wie oben beschrieben formatieren? – Suge

Antwort

1

Es gibt nur einen self, und du bist seine some_name in B.__init__ überschrieben werden. Vielleicht sind Sie an C++ gewöhnt, wo es zwei getrennte Felder geben würde, A.some_name und B.some_name. Dieses Konzept gilt nicht für Python, bei dem Attribute dynamisch bei der Zuweisung erstellt werden.

+0

Also wie kann ich dieses Problem lösen? – Suge

+0

@zkz: Was ist das Problem? Das ist das erwartete Python-Verhalten. – kriss

+0

@zkz, müssen Sie eindeutige Namen für jedes Attribut auswählen und verhindern, dass die Klassen aufeinander treten. –

5

Sie haben hier nur ein einziges Objekt; Die some_name-Eigenschaft wird von Methoden aus allen geerbten Klassen gemeinsam genutzt. Sie rufen A.__init__, die es auf A setzt, dann B.__init__, die es zu B ändert.

Beachten Sie auch, dass Sie Grundmethoden falsch aufrufen; verwenden super:

class A(object): 
    def __init__(self): 
     self.some_name = 'A' 
     super(A, self).__init__() 

    def print_a(self): 
     print self.some_name 

class B(object): 
    def __init__(self): 
     self.some_name = 'B' 
     super(B, self).__init__() 

    def print_b(self): 
     print self.some_name 

class C(A, B): 
    def __init__(self): 
     super(C, self).__init__() 

if __name__ == '__main__': 
    c = C() 
    c.print_a() 
+0

Was soll ich im zweiten Fall oben tun, wo ich afferente Parameter mit dem gleichen Schlüssel möchte, wenn die Superklasse __init__? – Suge

+0

Ich bin mir nicht sicher, was Sie fragen, aber Sie können nicht unterschiedliche Eigenschaften für dasselbe Objekt mit dem gleichen Namen haben. Sie sind das gleiche Objekt, das an derselben Stelle gespeichert ist: 'c .__ dict__', das ist einfach ein normales Python-Wörterbuch. –

+2

Beachten Sie, dass Sie 'self .__ some_name' sagen können, wodurch ein halb-privates Attribut für diese Klasse erstellt wird. Es wird tatsächlich Attribute namens zB erstellen. '_A__some_name' und' _B__some_name'. Dies wird jedoch sehr selten verwendet und ich empfehle es nicht. –

1

Sagen Sie bitte C Namen für einige Objekte der Typen A festlegen möchten, und B und später einige print_a und print_b Methoden auf Objekte vom Typ C aufrufen, diese Namen zurückbekommen?

Sie können diese Art von Verhalten mit C++ - Vererbungsmodell erhalten, aber Python-Modell ist sehr unterschiedlich. Nur ein Objekt mit einem Satz von Feldern. Wenn Sie das C++ - Verhalten wollen, ist der einfachste Weg vermutlich das Deklarieren von Unterobjekten (und es sieht so aus, als ob ein allgemeiner Missbrauch der Vererbung über die Komposition stattfindet).

Sieht aus wie Sie versuchen, so etwas wie unten zu tun:

class Printable(object): 
    def __init__(self, name): 
     self.name = name 

    def myprint(self): 
     print self.name 

class C(object): 
    def __init__(self): 
     self.a = Printable('A') 
     self.b = Printable('B') 

    def print_a(self): 
     self.a.myprint() 

    def print_b(self): 
     self.a.myprint() 

if __name__ == '__main__': 
    c = C() 
    c.print_a() 
+0

Das obige Beispiel ist nur eine Zusammenfassung meines Problems. Es ist komplexer in meinem Fall, wo ich meine Bedürfnisse von Ihrem Weg nicht erfüllen kann. Ich brauche einen Weg wie C++. – Suge

+1

@zkz: Sie sollten Ihr tatsächliches Problem erklären, weil das, was Sie sagen, sehr unwahrscheinlich ist.** Alle ** C++ - ähnlichen Vererbungsmodelle können mithilfe von Komposition verwaltet werden. Wenn Ihr Problem darin besteht, den Methodennamen von Unterobjekten zu finden, ist es sehr einfach, Python-Introspektionstools (getattr) zu verwenden. Oder ist das Problem mit einer gemeinsamen Basisklasse? Eigentlich ist die Vererbung niemals obligatorisch, nur eine Möglichkeit, Konzepte in Code zu mappen, und in vielen Fällen habe ich gesehen, dass es verwendet wird, um Dinge zu tun, die definitiv nicht mit Vererbung gemacht werden sollten. – kriss