簡體   English   中英

Python中的RAII:__del__有什么意義?

[英]RAII in Python: What's the point of __del__?

乍一看,Python的__del__特殊方法似乎提供了析構函數在C ++中具有的相同優勢。 但根據Python文檔( https://docs.python.org/3.4/reference/datamodel.html ), 無法保證您的對象的__del__方法完全被調用!

無法保證為解釋器退出時仍然存在的對象調用__del__ ()方法。

換句話說,這個方法沒用! 不是嗎? 可能會或可能不會被調用的鈎子函數確實沒有多大好處,因此__del__對RAII沒有任何提供。 如果我有一些必要的清理,我不需要它運行一些時間 ,哦,當GC感覺它真的,我需要它可靠,確定和100%的時間運行

我知道Python提供了上下文管理器,它對於該任務更有用,但為什么__del__一直保持不變? 重點是什么?

__del__是終結者。 它不是一個析構函數。 終結者和破壞者是完全不同的動物。

可以可靠地調用析構函數,並且只存在具有確定性內存管理的語言(例如C ++)。 Python的上下文管理器( with語句)在某些情況下可以實現類似的效果。 這些是可靠的,因為物體的壽命是精確固定的; 在C ++中,對象在顯式delete或在退出某個范圍時(或當智能指針刪除它們以響應其自身的破壞時)會死亡。 這就是析構函數運行的時候。

終結器不能可靠地調用。 終結器的唯一有效用途是作為緊急安全網 (注意:本文是從.NET角度編寫的,但概念轉換得相當好)。 例如, open()返回的文件對象在完成時自動關閉。 但你仍然應該自己關閉它們(例如使用with語句)。 這是因為垃圾收集器動態地銷毀對象,垃圾收集器可能會立即運行,也可能不會立即運行,並且通過分代垃圾收集,它可能會或可能不會收集任何給定傳遞中的某些對象。 由於沒有人知道我們將來可能會發明什么樣的優化,因此最安全地假設您無法知道垃圾收集器何時會收集您的對象。 這意味着你不能依賴終結者。

在CPython的特定情況下,由於使用引用計數(比垃圾收集更簡單,更可預測),您可以得到更強的保證。 如果您可以確保永遠不會創建涉及給定對象的引用循環,則將在可預測的位置調用該對象的終結器(當最后一個引用死亡時)。 這只適用於CPython,參考實現,而不是 PyPy,IronPython,Jython或任何其他實現。

因為__del__確實被調用了。 只是它不清楚它何時會發生,因為在CPython中如果你有循環引用,refcount機制不能處理對象回收(因此它通過__del__完成)並且必須將它委托給垃圾收集器。

垃圾收集器然后有一個問題:他不知道打破循環引用的順序,因為這可能會觸發其他問題(例如,釋放在收集循環的一部分的另一個對象的最終化中將需要的內存,觸發段錯誤)。

你強調的一點是因為解釋器可能會因為阻止它執行清理的原因而退出(例如,它是segfaults,或者某些C模塊不禮貌地調用exit())。

安全對象最終確定的PEP 442已在3.4中完成。 我建議你看一下。

https://www.python.org/dev/peps/pep-0442/

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM