super in Newstyle-Klassen

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Benutzeravatar
Dookie
Python-Forum Veteran
Beiträge: 2010
Registriert: Freitag 11. Oktober 2002, 18:00
Wohnort: Salzburg
Kontaktdaten:

super in Newstyle-Klassen

Beitragvon Dookie » Sonntag 18. Juli 2004, 18:50

Hallo zusammen.

Milan stellte in einem Anderen Thread eine Frage zur Verwendung von super in Newstyle-Klassen. Hier will ich mal an einem kleinen Beispiel demonstrieren, was super für Vorteile bietet gegenüber dem Aufruf von Methoden der Elternklasse, wie er in Oldstyle-Klassen bei Mehrfachvererbung vorkommt.
Hier mal ein Beispiel mit Oldstyle:

Code: Alles auswählen

>>> class A:
...:     def __init__(self):
...:         print "__init__ von A"
...:

>>> class B(A):
...:     def __init__(self):
...:         A.__init__(self)
...:         print "__init__ von B"
...:

>>> class C(A):
....:     def __init__(self):
....:         A.__init__(self)
....:         print "__init__ von C"
....:

>>> class D(B,C):
....:     def __init__(self):
....:         B.__init__(self)
....:         C.__init__(self)
....:         print "__init__ von D"
....:


Klasse A ist die Basisklasse, die Klassen B und C sind von A abgeleitet.
Klasse D ist von B und C abgeleitet.
Was passiert nun, wenn wir ein Objekt der Klasse D instanziieren:

Code: Alles auswählen

>>> d = D()
__init__ von A
__init__ von B
__init__ von A
__init__ von C
__init__ von D

Wie zu sehen ist, wird __init__ von A zweimal aufgerufen. Das kann leicht zu seltsamen Verhalten von Merhoden führen und ist nur mit extra Aufwand zu umgehen.

versuchen wir das ganze mal mit Newstyle-Klassen und super:

Code: Alles auswählen

>>> class A(object):
....:     def __init__(self):
....:         super(A,self).__init__()
....:         print "__init__ von A"
....:

>>> class B(A):
....:     def __init__(self):
....:         super(B,self).__init__()
....:         print "__init__ von B"
....:

>>> class C(A):
....:     def __init__(self):
....:         super(C,self).__init__()
....:         print "__init__ von C"
....:

>>> class D(B, C):
....:     def __init__(self):
....:         super(D,self).__init__()
....:         print "__init__ von D"
....:


Schauen wir jetzt mal was passiert wenn wir D instanziieren:

Code: Alles auswählen

>>> d = D()
__init__ von A
__init__ von C
__init__ von B
__init__ von D


Jetzt wird __init__ von A nur noch einmal aufgerufen.

Dies ist nur ein Aspekt von super. Ein anderer ist, wie aus der Syntax zu sehen, wird an super als erster Parameter die Klasse übergeben, deren Elternklasse(n) angesprochen werden sollen. Jetzt kann, ohne im restlichen Code Änderungen zu machen, auch mal eine andere Klasse als Elternklasse verwendet werden.

In __init__-Methode der Klasse A könnte der Superaufruf von __init__ auch wegbleiben. Ich mache es aber auch bei Klassen die von z.B. object abgeletet sind, da ich dann bei späteren Änderungen an der Klasse auch eine andere Basisklasse eintragen kann ohne sonstwo im Code etwas anpassen zu müssen.


Gruß

Dookie

Code: Alles auswählen

#!/usr/bin/env python
import this

Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder