514 Stimmen

Wie ruft man den Superkonstruktor in Python auf?

klasse A:
    def __init__(self):
        print("Welt")

klasse B(A):
    def __init__(self):
       print("Hallo")

B()  # Ausgabe: Hallo

In allen anderen Sprachen, mit denen ich gearbeitet habe, wird der Super-Konstruktor implizit aufgerufen. Wie ruft man ihn in Python auf? Ich würde erwarten super(self), aber das funktioniert nicht.

1 Stimmen

Sie sollten betonen, dass Sie eine Antwort möchten, die den abgeleiteten Klassennamen nicht verwendet. z.B. (Pseudocode): super().__init__(args...)

1 Stimmen

Du solltest Aidan Gomez Antwort akzeptieren. Es würde uns viel Zeit sparen, da sie eine Antwort sowohl in Python 2 als auch in 3 hat.

1 Stimmen

Python 2 wird nicht mehr offiziell unterstützt. Auch seine Antwort kam 5 Jahre später.

17voto

Shital Shah Punkte 54846

Kurze Antwort

super(DerivedClass, self).__init__()

Lange Antwort

Was macht super()?

Es nimmt den angegebenen Klassennamen, sucht nach seinen Basisklassen (Python erlaubt Mehrfachvererbung) und sucht nach der Methode (__init__ in diesem Fall) in jeder von ihnen von links nach rechts. Sobald es die verfügbare Methode findet, wird sie aufgerufen und die Suche beendet.

Wie rufe ich init aller Basisklassen auf?

Oben funktioniert es, wenn Sie nur eine Basisklasse haben. Aber Python erlaubt Mehrfachvererbung und Sie möchten sicherstellen, dass alle Basisklassen ordnungsgemäß initialisiert werden. Um dies zu tun, sollte jede Basisklasse init aufrufen:

class Base1:
  def __init__(self):
    super(Base1, self).__init__()

class Base2:
  def __init__(self):
    super(Base2, self).__init__()

class Derived(Base1, Base2):
  def __init__(self):
    super(Derived, self).__init__()

Was passiert, wenn ich vergesse, init für super aufzurufen?

Der Konstruktor (__new__) wird in einer Kette aufgerufen (wie in C++ und Java). Sobald die Instanz erstellt ist, wird nur der Initialisierer dieser Instanz (__init__) aufgerufen, ohne eine implizite Kette zu ihrer Superklasse.

0 Stimmen

__new__ ist ebenfalls nicht verknüpft. Wenn alle drei Klassen in Ihrem Beispiel __new__ definiert haben, aber super().__new__() nicht verwendet haben, würde Derived() Derived.__new__ aufrufen, aber nicht Base1.__new__ oder Base2.__new__. Ein __new__, das nicht den __new__ seines Elternteils aufruft, ist jedoch fast nutzlos, weil letztendlich object.__new__ das einzige ist, das tatsächlich eine neue Instanz von irgendetwas erstellt.

0 Stimmen

PyLint empfiehlt die Verwendung von Python 3 Style super() ohne Argumente

-3voto

lackadaisical Punkte 1428

Ich benutze die folgende Formel, die auf früheren Antworten basiert:

class A(object):
 def __init__(self):
   print "Welt"

class B(A):
 def __init__(self):
   print "Hallo"
   super(self.__class__, self).__init__()

B()

Auf diese Weise müssen Sie den Klassennamen nicht beim Aufruf von super wiederholen. Das kann nützlich sein, wenn Sie eine große Anzahl von Klassen codieren und Ihren Code in den Initialisierungsmethoden unabhängig vom Klassennamen machen möchten.

11 Stimmen

Aber Sie werden eine unendliche Rekursion erhalten, wenn Sie entscheiden, B mit C zu erweitern, und self.__class__ zeigt auf C(B) anstelle von B(A), also zeigt super(self.__class__, self) zurück zu B anstelle von A.

15 Stimmen

Dies führt zu unendlichen Rekursionsfehlern, wenn Sie B untergeordnet sind. Verwenden Sie nicht self.__class__ oder type(self), entweder geben Sie eine explizite Klasse an (B hier) oder verwenden Sie in Python 3 super() ohne Argumente.

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