[python] Destruktor von übergeordneter Klasse aufrufen


Enumerator

Mitglied Kamel
Hi!

Aus Spaß an der Freude dacht' ich mir heute zum Feierabend: "...was soll's? Lernst' halt Python..".
Bin auch recht fix voran gekommen, allerdings bereitet mir die OOP etwas Kopfzerbrechen: Vielleicht kann mir jemand mal erklären warum im folgenden der (vererbte) Destruktor der Klasse "Person" nicht aufgerufen wird?
Bzw. warum Sätze wie "John Lennon stirbt." und "Ringo Starr lebt aber noch!" nicht ausgegeben werden?
Python:
#!/usr/bin/env python
# coding=UTF-8

import sys
echo = sys.stdout.write

class Person:
    def __init__(self, name):
        self.name = name
        print self.__class__._Artikel, self.__class__.__name__, self.name, self.__class__._Entsteht
    def __del__(self):
        print self.__class__._Artikel, self.__class__.__name__, self.name, self.__class__._Verschwindet
    def sagt(self, nachricht):
        sys.stdout.write(self.name)
        print "sagt:", nachricht

Person._Entsteht = "entsteht."
Person._Verschwindet = "veschwindet."
Person._Artikel = "Die"

class Mensch(Person):
    def __del__(self):
        print self.name, "geht's nicht gut..."
#       Person.__del__(self)

Mensch._Entsteht = "wird geboren."
Mensch._Verschwindet = "stirbt."
Mensch._Artikel = "Der"

class Musiker(Mensch):
    pass

namen = [ "Stuart Sutcliffe", "Ringo Starr", "John Lennon", "Pete Best",
    "Paul McCartney", "George Harrison" ]
musiker = {}

for iter in range(len(namen)):
    musiker[namen[iter]] = Musiker(namen[iter])

reihenfolge = (0, 2, -1)

for iter in reihenfolge:
    del musiker[namen[iter]]

Mensch._Verschwindet = "lebt aber noch!"
Die auskommentierte Zeile 24 wirft einen sehr abenteuerlichen Fehler den ich zwar verstehe --
dennoch überrascht es mich das das nicht die Lösung des o.g. Problems ist, zumal es im Konstruktor funktioniert..

Dank und Gruß
Enum
 
Bin auch recht fix voran gekommen, allerdings bereitet mir die OOP etwas Kopfzerbrechen: Vielleicht kann mir jemand mal erklären warum im folgenden der (vererbte) Destruktor der Klasse "Person" nicht aufgerufen wird?
Bzw. warum Sätze wie "John Lennon stirbt." und "Ringo Starr lebt aber noch!" nicht ausgegeben werden?
Weil die Semantik von __del__ nun mal so ist (Quelle).

Die auskommentierte Zeile 24 wirft einen sehr abenteuerlichen Fehler den ich zwar verstehe --
dennoch überrascht es mich das das nicht die Lösung des o.g. Problems ist, zumal es im Konstruktor funktioniert..
Ich kann im Konstruktor keinen zu Person.__del__(self) äquivalenten Aufruf erkennen. Was genau meinst du damit? __del__ entspricht (nicht nur in dieser Hinsicht) übrigens nicht dem Destruktor aus bspw. C++. Es wird nämlich nicht mal garantiert, dass die Methode beim Skriptende für alle noch lebenden Objekte aufgerufen wird. In den meisten Fällen braucht man aber Destruktoren in einer Sprache mit einem GC auch überhaupt nicht.

Grüße,
Matthias
 

Enumerator

Mitglied Kamel
Hi Matthias!

Ich kann im Konstruktor keinen zu Person.__del__(self) äquivalenten Aufruf erkennen.
Sorry, ich hatte zuvor im Skript eine weitere Klasse:
Python:
class Gruppe(Person):
    def __init__(self, name):
        Person.__init__(self, name)
        self.mitglieder = []
# ...

Was genau meinst du damit? __del__ entspricht (nicht nur in dieser Hinsicht) übrigens nicht dem Destruktor aus bspw. C++. Es wird nämlich nicht mal garantiert, dass die Methode beim Skriptende für alle noch lebenden Objekte aufgerufen wird. In den meisten Fällen braucht man aber Destruktoren in einer Sprache mit einem GC auch überhaupt nicht.
Kein Zweifel. Dennoch ist es IMHO wichtig, das Verhalten des GC genau zu kennen, u.A. um mit (weak-) Referenzen und Dergleichen sowie C-modulen sicher spielen zu können.
In diesem speziellen Fall wollte ich eigentlich nur in Erfahrung bringen, wann genau welcher Destruktor aufgerufen wird: Wenn z.B. die Klasse Gruppe das einzige Objekt ist welches überhaupt Referenzen zu bestimmten Personen hält ist es doch sehr wichtig, ob zuerst die Destruktoren der Person Klasse (für die Mitglieder) aufgerufen werden oder erst die Gruppe vernichtet wird...
Wie auch immer, die gestellten Fragen hat das Skript für mich ja beantwortet. Nur hat es auch eine neue Frage aufgeworfen - und die ist Thema dieses Threads :p

Weil die Semantik von __del__ nun mal so ist (Quelle).
Ok. Wie zur H*lle kann ich dann ein solches verhalten implementieren? Tante Google hat zwar ein paar Tweaks ausgespuckt (so in der Richtung for base in self.__class__.__bases__) aber keine davon scheint wirklich sicher, schon gar nicht wenn weitere Ableitungen vorgenommen werden -
Und soweit mich meine Englisch-Kenntnisse bringen, beschreibt die Doku die Du verlinkt hast auch nur das Problem und nicht die Lösung...

Gruß
Enum