2017-12-31 65 views
1

Ich habe einigen Test heute:Python-Klasse Standardwert Vererbung

class SuperC(): 
    def __init__(self, a, b, c, d='D0'): 
     self.A = a 
     self.B = b 
     self.C = c 
     self.D = d 
     self.E = 'E0' 

sup = SuperC('A0', 'B0', 'C0') 
print(sup.A) # >>> A0 
print(sup.B) # >>> B0 
print(sup.C) # >>> C0 
print(sup.D) # >>> D0 
print(sup.E) # >>> E0 

Sie in der übergeordneten Klasse sehen können, gibt es zwei Arten von Standardwert (d und e) d ist ‚offen‘, während e Jetzt ist eine Art 'versteckte'

, wenn ich eine Unterklasse, mit einem neuen Attribut 'f' zu erstellen:

class SubC1(SuperC): 
    def __init__(self, a, b, c, f): 
     super().__init__(a, b, c) 
     self.F = f 

sub1 = SubC1('A1', 'B1', 'C1', 'F1') 
print(sub1.A) # >>> A1 
print(sub1.B) # >>> B1 
print(sub1.C) # >>> C1 
print(sub1.D) # >>> D0 
print(sub1.E) # >>> E0 
print(sub1.F) # >>> F1 

kann ich sehen, dass a, b, c gute Vererbung bekommen hat und neue Werte annehmen kann. Aber ich habe nicht d und e in super().__init__() wählen. ABER sie haben auch perfekte Vererbung, und das Problem ist, dass ich den Wert von d und e beim Erstellen der Instanz der Unterklasse nicht ändern kann. und f funktioniert gut.

Jetzt erstelle ich eine andere Unterklasse:

class SubC2(SuperC): 
     def __init__(self, a, b, c, f, d='D2'): 
      super().__init__(a, b, c, d) 
      self.F = f 

sub2 = SubC2('A2', 'B2', 'C2', 'F2') 
print(sub2.A) # >>> A2 
print(sub2.B) # >>> B2 
print(sub2.C) # >>> C2 
print(sub2.D) # >>> D2  
print(sub2.E) # >>> E0 # hidden e is still E0 
print(sub2.F) # >>> F2 

mit d geschrieben sowohl in __init__() und super().__init__(), jetzt kann man erkennen, d perfektes Erbe erhalten und kann mit neuem Standardwert oder neuem Wert in einer neuen Instanz überschrieben werden. aber e wird immer noch E0

Es ist wie die einzige gute Möglichkeit scheint, ist:

class SubC3(SuperC): 
    def __init__(self, a, b, c, f, d='new D', e='new E'): 
     super().__init__(a, b, c) 
     self.D = d # set new 
     self.E = e # set new 
     self.F = f 

sub3 = SubC3('A3', 'B3', 'C3', 'F3') 
print(sub3.A) # >>> A3 
print(sub3.B) # >>> B3 
print(sub3.C) # >>> C3 
print(sub3.D) # >>> new D 
print(sub3.E) # >>> new E 
print(sub3.F) # >>> F3 

Jetzt, wo ich neuen Standardwert/Instanz-Wert sowohl d und e mit Marke haben kann, aber wenn links nicht angezeigt , dann werden sie nicht von der SuperC erben

Meine Frage ist, denke ich, das ist der richtige Weg? Habe ich etwas vermisst? Gibt es bessere Möglichkeiten, die Vererbung von Standardwerten festzulegen?

Oder vielleicht in einer Weise, dass e soll nicht geändert werden, wenn auf diese Weise geschrieben? weil es ein fundamentales Attribut sein könnte, das ein konstanter Wert sowohl für die Oberklasse als auch für die Unterklasse sein soll?

+1

Diese Die Frage sollte wahrscheinlich vollständig auf der Grundlage von Meinungen geschlossen werden. Es gibt keinen "richtigen" oder "besten" Weg, dies zu tun. Es gibt nichts "_wrong_" mit irgendwelchen Ihrer Beispielklassen. Was Sie verwenden, läuft darauf hinaus, wie Sie mit Ihrer Klasse interagieren möchten. –

Antwort

1

Ich scheine das das Problem nicht verstehen ...

Wenn Sie dies tun:

class SuperC(): 
    def __init__(self, a, b, c, d='D0'): 
     self.A = a 
     self.B = b 
     self.C = c 
     self.D = d 
     self.E = 'E0' 

self.E ist nicht "versteckt".Es hat gerade einen fest codierten Wert: die Zeichenfolge "E0" und d='D0' als gelesen werden Wenn Sie mit einem bestimmten Wert im d Argumente genannt werden, verwenden, dass man, anders, verwenden Sie einfach die Zeichenfolge "D0" (es ist ein named optional argument)

Wenn Sie dies tun:

class SubC3(SuperC): 
    def __init__(self, a, b, c, f, d='new D', e='new E'): 
     super().__init__(a, b, c) 
     self.D = d # set new 
     self.E = e # set new 
     self.F = f 

Was passiert, ist, dass der Anruf zu super().__init__ mit dem, was a, b, c Argumenten eine Klasse erstellt Sie bestanden, ein self.E und die fest codierten "E0". Danach machen Sie self.E = e und dann überschreiben Sie das "E0" mit dem Wert des Arguments e.

Try this:

class SubC3(SuperC): 
    def __init__(self, a, b, c, f, d='new D', e='new E'): 
     super().__init__(a, b, c) 
     print("Before overwrite=%s" % self.E) 
     self.D = d # set new 
     self.E = e # set new 
     print("After overwrite=%s" % self.E) 
     self.F = f 

sub3 = SubC3('A3', 'B3', 'C3', 'F3') 

Sie werden feststellen, dass direkt nach der init sehen, sehen Sie self.E"E0" zu sein und dann ist es überschrieben:

Before overwrite=E0 
After overwrite=new E 

Über die d:

Try dies:

class SubC3(SuperC): 
    def __init__(self, a, b, c, f, d='new D', e='new E'): 
     super().__init__(a, b, c) 
     self.E = e # set new 
     self.F = f 

sub3 = SubC3('A3', 'B3', 'C3', 'F3') 
print(sub3.D) 

Sie werden sehen, dass es D0 ist, weil Sie keine d zum Super bestanden hat, und Sie haben es nicht in SubC3.__init__ überschreiben, so dass es verwendet, um die standardmäßig im SuperC.__init__ (wo man d='D0' tun)

+0

Ich verstehe was du gesagt hast und wie 'd' und' e' bestanden wurden. Ich frage tatsächlich, was der beste Weg ist, um die Attribute von der Oberklasse zur Unterklasse zu übergeben, wenn in der Oberklasse ein Standardwert angegeben wurde. –

+0

Sie meinen, was mit dem 'd = ...' zu tun ist, da beide in 'SubC3' und' SuperC' definiert sind? – BorrajaX

+0

Ich glaube, es gibt keine kanonische Art ... Für mich hängt alles von der tatsächlichen Struktur ab, und was _feels_ natürlich. Wenn Sie eine Basisklasse haben, die Sie ableiten wollen, und in einigen Unterklassen denken Sie, Sie brauchen ein Argument, aber in anderen Unterklassen brauchen Sie es nicht, dann funktioniert ein kwarg (das 'd =" D0 "') gut. Andernfalls, wenn alle Ihre Unterklassen das Argument benötigen, machen Sie es nicht optional ... Ich würde sagen, es hängt von Ihrem tatsächlichen Szenario ab. – BorrajaX