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).
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?
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.
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.
Tags und Links python