3275 Stimmen

Verständnis von Python super() mit __init__() Methoden

Warum ist super() verwendet?

Gibt es einen Unterschied zwischen der Verwendung von Base.__init__ y super().__init__ ?

class Base(object):
    def __init__(self):
        print "Base created"

class ChildA(Base):
    def __init__(self):
        Base.__init__(self)

class ChildB(Base):
    def __init__(self):
        super(ChildB, self).__init__()

ChildA() 
ChildB()

35 Stimmen

Dies ist eine sehr einfache Einführung in den Unterricht, die es wert ist, durchgenommen zu werden: realpython.com/python-super/ . Es ist leichter zu verdauen als die gegebenen Antworten, die für die meisten von uns vermutlich zu detailliert in der Implementierung von Python sind. Es hat auch Beispiele, um es konkret zu machen.

0 Stimmen

Ich habe es immer noch nicht verstanden. Ich möchte eine class Event(tuple) die Tupel (Zeitstempel, Beschreibung) erstellt, wobei der Zeitstempel standardmäßig die aktuelle Zeit sein sollte. Also, etwas wie e = Event(description="stored the current time") sollte eine Instanz der Unterklasse Event des Tupels (1653520485,"stored...") . Aber in __init__() Ich kann nicht ändern self wie ich es für eine Unterklasse von dict . Also dachte ich, ich könnte die super().__init__ um die Komponenten des Tupels zu setzen self . Darf ich?

62voto

Devin Jeanpierre Punkte 87113

Es gibt keine, wirklich. super() schaut sich die nächste Klasse in der MRO (method resolution order, aufgerufen mit cls.__mro__ ), um die Methoden aufzurufen. Der bloße Aufruf der Basis __init__ ruft die Basis __init__ . Zufälligerweise hat das MRO genau einen Gegenstand - die Basis. Sie tun also genau das Gleiche, aber auf eine schönere Art und Weise mit super() (insbesondere, wenn Sie später eine Mehrfachvererbung anstreben).

3 Stimmen

Ich verstehe. Könnten Sie ein wenig näher erläutern, warum es schöner ist, super() mit Mehrfachvererbung zu verwenden? Für mich ist base.__init__(self) kürzer (sauberer). Wenn ich zwei Basisklassen hätte, wären es zwei dieser Zeilen, oder zwei super()-Zeilen. Oder habe ich missverstanden, was Sie mit "schöner" meinten?

8 Stimmen

Eigentlich wäre es eine einzige super()-Zeile. Bei Mehrfachvererbung ist die MRO immer noch flach. Also ruft der erste super().__init__-Aufruf den Aufruf der nächsten Klasse init die dann die nächste aufruft, und so weiter. Sie sollten sich wirklich einige Dokumente dazu ansehen.

0 Stimmen

Die MRO der Kindklasse enthält ebenfalls ein Objekt - die MRO einer Klasse ist in der mro Klassenvariable.

45voto

RubenLaguna Punkte 17855

Der Hauptunterschied besteht darin, dass ChildA.__init__ wird bedingungslos aufrufen Base.__init__ während ChildB.__init__ wird anrufen __init__ en welche Klasse auch immer es sein mag ChildB Vorfahre in self die Ahnenreihe von (die von dem abweichen können, was Sie erwarten).

Wenn Sie eine ClassC die Mehrfachvererbung verwendet:

class Mixin(Base):
  def __init__(self):
    print "Mixin stuff"
    super(Mixin, self).__init__()

class ChildC(ChildB, Mixin):  # Mixin is now between ChildB and Base
  pass

ChildC()
help(ChildC) # shows that the Method Resolution Order is ChildC->ChildB->Mixin->Base

dann Base ist nicht mehr der Elternteil von ChildB para ChildC Instanzen. Jetzt super(ChildB, self) zeigt auf Mixin wenn self ist eine ChildC Instanz.

Sie haben eingefügt Mixin zwischendurch ChildB y Base . Und Sie können die Vorteile nutzen mit super()

Wenn Sie also Ihre Klassen so gestalten, dass sie in einem Szenario der kooperativen Mehrfachvererbung verwendet werden können, verwenden Sie super weil man nicht wirklich weiß, wer zur Laufzeit der Vorfahre sein wird.

El super überlegt super Beitrag y pycon 2015 Begleitvideo erklären dies ziemlich gut.

4 Stimmen

Dies. Die Bedeutung von super(ChildB, self) ändert sich in Abhängigkeit von der MRO des Objekts, auf das mit self die erst zur Laufzeit bekannt sein kann. Mit anderen Worten, der Autor von ChildB hat keine Möglichkeit zu wissen, was super() in allen Fällen beschließen werden, es sei denn, sie können garantieren, dass ChildB wird niemals unterklassig sein.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X