Warum braucht man super() nur bei __init__()-Methoden?

2 Antworten

Vom Fragesteller als hilfreich ausgezeichnet
Warum braucht man super() nur bei __init__()-Methoden?

Die Aussage ist nicht unbedingt richtig. Du kannst super() auch bei anderen Aufrufen nutzen, ist dort aber je nach Kontext auch überflüssig (siehe Beispiel unten)

Aber wieso bei anderen Methoden nicht?

Okay, holen wir etwas aus:

Das ganze geschieht im Kontext der Vererbung - wenn eine Klasse von anderen Klassen erbt.

Einfaches Beispiel - Klasse "Cat" erbt von der Klasse "Animal"

class Animal:
  pass

class Cat(Animal):
  pass

mit super() referenzierst du hierbei die Elternklasse, von der geerbt wird, und rufst explizit die dort implementierte Methode auf.

Du kannst super() auch bei anderen Methoden nutzen, das ist nicht nur auf __init__ beschränkt. Nur ergibt das besonders Sinn dort, da __init__ eben das Objekt initialisiert und entsprechende Zeilen bei Objekt-Erstellung ausführt. Du gibst darüber z.B. an, dass das Objekt folgende Attribute speichern soll.

Überschreibst du die init-Methode der Kindklasse, da du für diese eben eine zusätzliche Funktionalität implementieren möchtest, müsstest du für die gleiche Funktionalität den Inhalt der init-Methode der Elternklasse kopieren. Um das zu umgehen, doppelten Code zu vermeiden und es aufgeräumter zu haben, rufst du dann anschließend noch die init-Methode der Elternklasse auf.

Beispiel:

class Animal:
  def __init__(self):
    print("I am an animal!")
    
  def run(self):
    print("I am running!")

class Cat(Animal):
  def __init__(self):
    print("I am a cat!")
    
  def run(self):
    print("I am running, meow!")

if __name__ == "__main__":
  cat = Cat()
  cat.run()

Hier erbt die Klasse "Cat" von Animal. Du überschreibst jedoch die init-Methode der Klasse Animal durch eine eigene.

Führst du also obriges Skript aus, kommt als Ausgabe:

I am a cat!
I am running, meow!

Von hier kannst du etwas rumspielen, um Änderungen selbst mitzuerleben: Ändern wir einfach mal die Klasse Cat. Wir rufen in beiden Methoden auch noch die Eltern-Methode auf.

class Cat(Animal):
  def __init__(self):
    super().__init__()
    print("I am a cat!")
    
  def run(self):
    super().run()
    print("I am running, meow!")

Belassen wir den Rest des Skriptes jetzt unverändert, erhalten wir folgende Ausgabe:

I am an animal!
I am a cat!
I am running!
I am running, meow!

Entfernst du aus der Klasse "Cat" die Methode "run" und fühst den Code aus, kommt folgende Ausgabe - da wird dann die Methode der Elternklasse genommen, da es diese in der Kindklasse nicht gibt:

I am an animal!
I am a cat!
I am running!

gehen wir noch einen Schritt weiter und entfernen alles aus der Cat-Klasse:

class Animal:
  def __init__(self):
    print("I am an animal!")
    
  def run(self):
    print("I am running!")

class Cat(Animal):
    pass

if __name__ == "__main__":
  cat = Cat()
  cat.run()

das ergibt folgende Ausgabe, da hier alles von der Elternklasse geerbt wird

I am an animal!
I am running!

Das ganze ist auch nicht darauf beschränkt, dass du die gleichnamige Funktion aufrufst:

class Animal:
  def __init__(self):
    print("I am an animal!")

  def die(self):
    print("I am dead now")

class Cat(Animal):
    def __init__(self):
        super().__init__()
        super().die()

if __name__ == "__main__":
  cat = Cat()

Da das Objekt Cat jedoch von Animal erbt und die Methode "die" nicht überschreibt, ist die init-Methode auch äquivalent zu:

class Cat(Animal):
  def __init__(self):
    super().__init__()
    self.die()
Woher ich das weiß:Studium / Ausbildung – Abgeschlossenes Studium der Informatik (B.Sc.)

Wenn Du es nur da brauchst, dann hast Du super() bisher nicht richtig verstanden und auch vielleicht nicht genug benutzt.

super() ist NICHT wie von W00dp3ckr bescchrieben die Init Methode von der man erbt. super() liefert ein Proxy Objekt der Klasse von der Du erbst und leitet Methodenaufrufe an dieses Proxy-Objekt weiter.

class C(B):
    def method(self, arg):
        super().method(arg)

Würde als Beispiel im Methodenaufruf method der Class C zunächst method aus der Elternklasse aufrufen.