Vererbung

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.
Antworten
kostonstyle
User
Beiträge: 148
Registriert: Sonntag 2. November 2008, 12:13

Hallo habe eine Frage zu der Vererbung, dieser Code hier

Code: Alles auswählen

class DahlManager(models.Manager):
    def get_query_set(self):
        return super(DahlManager, self).get_query_set().filter(author='Roald Dahl')
Die Klasse DahlManager erbt von der Klasse Manager. Der Aufruf von Basisklasse super(DahlManager, ..... das hängt bei mir. Wenn ich die Definition von Manager anschaue

Code: Alles auswählen

class Manager(object):
    # Tracks each time a Manager instance is created. Used to retain order.
    creation_counter = 0

    def __init__(self):
        super(Manager, self).__init__()
        self._set_creation_counter()
        self.model = None
        self._inherited = False
hier wird wieder der constructor von der basisklasse aufgerufen, aber warum wird hier das Manager Objekt übergeben?

Vielen Dank kostonstyle
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

Die Syntax von `super` ist folgende:
``super(ClassObject, InstanceObject).supers_function()``

ClassObject ist das Objekt, dessen Basisklasse du ansprechen willst; InstanceObject ist das Objekt, das als Exemplar uebergeben wird (Es wird kein neues erzeugt! Z.B. arbeitet ``__init__`` im Manager-Code auf dem Manager-Exemplar, nicht auf dem object-Exemplar).
kostonstyle
User
Beiträge: 148
Registriert: Sonntag 2. November 2008, 12:13

bei diesem beispiel, heisst das, dass der Befehl super das Objekt Manager aufruft, sich selber? Ist das ein rekursiver Aufruf?
Was bewirkt den so ein Befehl, bitte ein konkretes Beispiel!

Danke kostonstyle
Darii
User
Beiträge: 1177
Registriert: Donnerstag 29. November 2007, 17:02

Nein, super ermittelt eine Superklasse von Manager und leitet die Methodenaufrufe weiter. Das ganze sieht nur so merkwürdig aus, da Python dynamisch ist und zudem Mehrfachvererbung unterstützt. Im Endeffekt stellt super sicher, dass jede Methode nur einmal aufgerufen wird. Am besten nimmst du es erstmal so hin, dass man das so schreiben muss.

PS: super ist eine Funktion kein Befehl.
Benutzeravatar
HWK
User
Beiträge: 1295
Registriert: Mittwoch 7. Juni 2006, 20:44

Vielleicht wird es verständlicher, wenn man super mit dem ähnlichen, wenn auch nicht identischen Aufruf

Code: Alles auswählen

Manager.__init__(self)
vergleicht?
MfG
HWK
kostonstyle
User
Beiträge: 148
Registriert: Sonntag 2. November 2008, 12:13

um alles zu verdeutlichen habe ich mir ein Beispiel programmiert

Code: Alles auswählen

class basis(object):
    def __init__(self):
        print("Basisklasse")
    
class sub(basis):
    def __init__(self):
        super(sub, self).__init__()
        print("Subklasse")

a = sub()
die Ausgabe

Code: Alles auswählen

Basisklasse
Subklasse
warum muss ich hier in der funktion die sub klasse angeben und auch self? Es würde viel logischer, anstatt sub, basis anzugeben, wegen die Mehrfachvererbung, damit der Compiler weiss, welche Basisklasse gemeint ist.
ein zweiter Versuch

Code: Alles auswählen

class basis(object):
    def __init__(self):
        print("Basisklasse")
    
class sub(basis):
    def __init__(self):
        super(basis, self).__init__()
        print("Subklasse")

a = sub()
die ausgabe

Code: Alles auswählen

Subklasse
die ausgabe ist nur subklasse..ahhh ist logisch, der compiler sucht ja nach der superklasse von basis.
noch ein dritter versucht

Code: Alles auswählen

class basis(object):
    def __init__(self):
        print("Basisklasse")
    
class sub(basis):
    def __init__(self):
        super.__init__()
        print("Subklasse")

a = sub()
warum erscheint eine fehlermeldung

Code: Alles auswählen

TypeError: descriptor '__init__' of 'super' object needs an argument
File "/Volumes/Develop/excourse.py", line 10, in <module>
  a = sub()
File "/Volumes/Develop/excourse.py", line 7, in __init__
  super.__init__()
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

kostonstyle hat geschrieben:warum muss ich hier in der funktion die sub klasse angeben und auch self? Es würde viel logischer, anstatt sub, basis anzugeben, wegen die Mehrfachvererbung, damit der Compiler weiss, welche Basisklasse gemeint ist.
Du hast `super` noch nicht verstanden. `super` sucht nach nach der Basisklasse anhand des Klassenobjekts und des Exemplars. Wuerdest du die Basisklasse angeben, waere `super` ueberfluessig und du koenntest das direkt aufrufen. Nebenbei weiss der Interpreter viel besser wie die Interna aussehen und wie er effizient als du.
kostonstyle hat geschrieben: warum erscheint eine fehlermeldung
Weil `super` immernoch eine Funktion ist (anders als in Java, falls du von dort kommst)
kostonstyle
User
Beiträge: 148
Registriert: Sonntag 2. November 2008, 12:13

so könnte eine Vererbung aufbauen

Code: Alles auswählen

class Base():
    def __init__(self, param):
        print "Base:", param
    def method(self, param):
        print "Base.method:", param

class Derived(Base):
    def __init__(self, param):
        Base.__init__(self, param)
        print "Derived:", param
    def method(self, param):
        Base.method(self, param)
        print "Derived.method:", param

d = Derived("me")
Hier wird basisklasse eindeutig aufgerufen.
Warum ist bei der super Funktion das Klassenobjekt sich selber(also z.B sub anstatt basis) und was ist überhaupt Examplar. Da Python die Mehrfachvererbung unterstützt, wie weiss die super Funktion, welche basisklasse er nehmen sollte?

Ich komme aus der ABAP Welt :-)

Danke kostonstyle
Darii
User
Beiträge: 1177
Registriert: Donnerstag 29. November 2007, 17:02

kostonstyle hat geschrieben:warum muss ich hier in der funktion die sub klasse angeben und auch self? Es würde viel logischer, anstatt sub, basis anzugeben, wegen die Mehrfachvererbung, damit der Compiler weiss, welche Basisklasse gemeint ist.
Nein, weil die Basisklassen deiner Klasse gesucht werden und nicht eine spezielle Klasse. Außerdem hast du vergessen bei deiner Basisklasse auch super() aufzurufen.
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

kostonstyle hat geschrieben:Da Python die Mehrfachvererbung unterstützt, wie weiss die super Funktion, welche basisklasse er nehmen sollte?
Wegen der MRO, viel spass beim durchkaempfen:
http://www.python.org/download/releases/2.3/mro/
Antworten