3

这个问题是我之前提出的一个问题的扩展:Python 委托模式 - 如何避免循环引用?阅读回复后,我决定澄清我的问题,但被要求单独发布。

开始:

  1. Python 文档中的一段(转载如下)指出,循环引用的对象不能保证垃圾收集。我在这里找到的一篇文章暗示了同样的事情。但是对我之前的问题的答复不同意。那么,我是否误解了这篇文章,或者我错过了更多细节?
  2. 我想使用弱引用,正如 Alex Martelli 对我是否应该担心 Python 中的循环引用?会完全避免在他的回复中提到的垃圾收集循环引用对象的开销吗?如果是这样,它是如何工作的?

相关的 Python 文档表明 Python 文档中的以下段落存在冲突:

CPython 实现细节:CPython 目前使用引用计数方案,对循环链接的垃圾进行(可选)延迟检测,该方案在大多数对象变得无法访问时立即收集它们,但不能保证收集包含循环引用的垃圾。有关控制循环垃圾收集的信息,请参阅 gc 模块的文档。其他实现的行为不同,CPython 可能会改变。当对象变得无法访问时,不要依赖于立即完成对象(例如:始终关闭文件)。

可以在此处找到原始形式的段落:http: //docs.python.org/reference/datamodel.html粗体设置是我的。

提前感谢您的任何回复。

4

2 回答 2

2

我认为,不能保证收集具有循环引用的对象的最重要原因是,根据设计,如果 Python 定义了一个方法,则从不收集具有循环引用的对象。有一个非常简单的原因 __del__

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

我不愿意说这是可能无法检测到具有循环引用的不可访问对象的唯一原因。可能有一些不寻常的情况可能会破坏 GC 的循环检测机制。但除非您__del__为您的对象之一定义,否则您可能没问题。不用担心,如果您发现性能问题,请使用 GC 广泛的调试选项。

于 2012-05-17T03:20:12.150 回答
1

当它说不能保证收集循环引用时,这正是它的意思。每当您的数据结构包含循环引用时,引用计数将始终非零,这意味着仅引用计数不足以决定何时删除它们。另一方面,在到达每个范围的末尾后查找所有循环引用将是耗时的——至少可以这么说。它将涉及分析具有非零引用计数的所有对象的关系。

也就是说,一般来说,我不认为你会有问题。对于轻量级脚本,您可以忽略它。对于其他人,您仍然需要在范围结束时进行一些清理工作(关闭文件,甚至删除循环引用),就像在 C 中一样,但它仍然不像 C 那样令人兴奋。

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

于 2012-05-17T02:17:13.707 回答