Ist es wirklich in __del__ möglich, Objekte zu schließen / zu verwerfen?

7

Ich habe darüber nachgedacht, wie ich Klassen in Python schreibe. Genauer gesagt, wie der Konstruktor implementiert ist und wie das Objekt zerstört werden soll. Ich möchte mich nicht auf die Referenzzählung von CPython verlassen, um die Objektbereinigung durchzuführen. Dies sagt mir grundsätzlich, dass ich mit Anweisungen die Lebensdauer meines Objekts verwalten soll und dass ich eine explizite close / dispose -Methode brauche (diese Methode könnte von __exit__ aufgerufen werden, wenn das Objekt auch ein Kontextmanager ist).

%Vor%

Wenn sich nun alle meine Objekte auf diese Weise verhalten und mein gesamter Code mit Anweisungen oder expliziten Aufrufen von close() (oder dispose() ) verwendet wird, sehe ich nicht wirklich die Notwendigkeit, irgendeinen Code in% co_de zu setzen %. Sollen wir wirklich __del__ verwenden, um unsere Objekte zu entsorgen?

    
Arlaharen 10.07.2009, 19:26
quelle

3 Antworten

13

Kurze Antwort: Nein.

Lange Antwort: Die Verwendung von __del__ ist schwierig, hauptsächlich weil es nicht garantiert ist, dass sie aufgerufen wird. Das bedeutet, dass du dort nicht Dinge tun kannst, die unbedingt gemacht werden müssen. Dies wiederum bedeutet, dass __del__ im Grunde nur für Aufräumarbeiten verwendet werden kann, die früher oder später sowieso stattfinden würden, wie das Bereinigen von Ressourcen, die beim Beenden des Prozesses bereinigt würden. Es ist also egal, ob __del__ dies nicht tut gerufen werden. Natürlich sind dies auch die gleichen Dinge, die Python für Sie tun wird. Das macht __del__ nutzlos.

Außerdem wird __del__ aufgerufen, wenn Python-Müll gesammelt wird, und Sie wollten nicht auf die Pythons-Müllsammlung warten, was bedeutet, dass Sie __del__ trotzdem nicht verwenden können.

Also, benutze __del__ nicht. Verwenden Sie stattdessen __enter__/__exit__ .

Zur Erinnerung: Hier ist ein Beispiel für eine nicht-zirkuläre Situation, in der der Destruktor nicht aufgerufen wurde:

%Vor%

OK, also ein Klassenattribut. Offensichtlich ist das ein besonderer Fall. Aber es zeigt nur, dass es nicht einfach ist, dafür zu sorgen, dass __del__ aufgerufen wird. Ich bin mir ziemlich sicher, dass ich mehr nicht-zirkuläre Situationen gesehen habe, in denen __del__ nicht aufgerufen wird.

    
Lennart Regebro 11.07.2009, 07:38
quelle
8

Nicht unbedingt. Bei zyklischen Verweisen treten Probleme auf. Eli Bendersky erklärt das in seinem Blogpost sehr gut:

ars 10.07.2009 19:37
quelle
0

Wenn Sie sicher sind, dass Sie keine zyklischen Referenzen verwenden, dann ist die Verwendung von __del__ auf diese Weise OK: Sobald der Referenzzähler auf Null geht, ruft die CPython-VM diese Methode auf und zerstört das Objekt.

Wenn Sie zyklische Referenzen verwenden möchten - denken Sie bitte sehr gründlich darüber nach, ob schwache Referenzen helfen können; In vielen Fällen sind zyklische Referenzen ein erstes Symptom für schlechtes Design.

Wenn Sie keine Kontrolle darüber haben, wie Ihr Objekt verwendet werden soll, ist die Verwendung von __del__ möglicherweise nicht sicher.

Wenn Sie JPython oder IronPython verwenden möchten, ist __del__ überhaupt nicht verlässlich, da die endgültige Objektzerstörung bei der Garbage Collection stattfindet und Sie das nicht kontrollieren können.

Insgesamt ist meiner Meinung nach __del__ normalerweise vollkommen sicher und gut; In vielen Situationen könnte es jedoch besser sein, einen Schritt zurückzutreten und das Problem aus einer anderen Perspektive zu betrachten. Eine gute Verwendung von try / except und von with contexts kann eine eher pythische Lösung sein.

    
Roberto Liffredo 10.07.2009 21:21
quelle

Tags und Links