Python的垃圾收集可以保证在所有情况下回收循环引用的对象吗?

时间:2012-05-17 02:06:33

标签: python garbage-collection circular-reference

这个问题是我之前提到的问题的延伸:Python Delegate Pattern - How to avoid circular reference?在阅读回复后,我决定澄清我的问题,但是被要求单独发布。

这里是:

  1. Python文档中的一篇文章(转载如下)表明,通过收集不能保证循环 引用的对象。我发现here的帖子暗示了同样的事情。但对我之前的问题的答复不同意。那么,我是否误解了这段经文还是有进一步的 我错过了哪些细节?
  2. 我认为使用弱引用,正如Alex Martelli对问题Should I worry about circular references in Python?的回复所述,可以避免垃圾收集完整回复中提到的循环引用对象的开销?如果是这样,它是如何工作的?
  3. 相关的Python文档表明,在Python的文档传递之后存在冲突:

      

    CPython实现细节:CPython目前使用的是   参考计数方案与(可选)延迟检测   循环链接垃圾,一旦收集到大多数物体   变得无法到达,但无法保证收集垃圾   包含循环引用。请参阅gc模块的文档   有关控制循环垃圾收集的信息。其他   实现方式不同,CPython可能会改变。不依赖   当物品无法到达时立即完成物品(例如:   总是关闭文件。)

    原文中的段落可以在这里找到:http://docs.python.org/reference/datamodel.html大胆的设置是我的。

    提前感谢您的回复。

2 个答案:

答案 0 :(得分:2)

我认为带有循环引用的对象不能被保证收集的最重要原因是,根据设计,Python 从不收集具有循环引用的对象< em>如果他们定义了 __del__ 方法。有一个漂亮的straightforward reason

  

Python不会自动收集此类循环,因为通常情况下,Python无法猜测运行__del__()方法的安全顺序。

我不愿意说这是唯一的原因可能无法检测到带有循环引用的无法访问的对象。可能有一些不寻常的情况会影响GC的循环检测机制。但除非您为其中一个对象定义__del__,否则可能确定。如果您发现性能问题,请不要担心,并使用GC的大量调试选项。

答案 1 :(得分:1)

当它表示无法保证收集循环引用时,这正是它的含义。只要数据结构包含循环引用,引用计数将始终为非零,这意味着单独引用计数不足以决定何时删除它们。另一方面,在到达每个范围的末尾之后找到所有循环引用将是耗时的 - 至少可以说。它将涉及使用非零引用计数分析所有对象的关系。

那就是说,一般来说,我不认为你会遇到问题。对于轻型脚本,您可以忽略它。对于其他人来说,你仍然需要在范围的最后做一些清理工作(关闭文件,甚至删除循环引用),就像在C中一样,但它仍然不像C那样令人生气。

如果它成为问题,只需在完成每个数据对象之前删除循环引用。