2012-05-17 75 views
3

这个问题是我之前问过的一个问题的扩展:Python Delegate Pattern - How to avoid circular reference?阅读答复后,我决定澄清我的问题,但被要求单独发布。Python的垃圾收集可以保证在任何情况下回收循环引用的对象吗?

这里所说:

  1. 在Python文档的通道(下面再现)指出garbaged集合时,不能确保圆形 引用的对象。我发现一篇文章here表明同样的事情。但对我先前的问题的答复不同意。那么,我是否误解了这段经文,或者是否有进一步的细节,我错过了?
  2. 我想使用一个弱引用,如Alex Martelli对Should I worry about circular references in Python?问题的回复所述,可以避免垃圾回收在他的回复中提到的循环引用对象的开销?如果是的话它是如何工作的?

其表明从Python的文档冲突的以下通道相关Python文档:

CPython的实现细节:CPython的目前采用的是 引用计数方案与(可选)延迟 环状连接垃圾的检测,一旦他们 变得无法到达,但是不保证收集包含循环引用的垃圾 。有关控制循环垃圾收集的信息,请参阅gc模块 的文档。其他 实现的行为不同,CPython可能会更改。不要依赖 在对象无法到达时立即完成对象定义(例如: 总是关闭文件)。

原始形式的文章可以在这里找到:http://docs.python.org/reference/datamodel.html大胆的设置是我的。

在此先感谢您的答复。

回答

2

我相信,随着循环引用的对象的最重要的原因是没有保证要收集的是,在设计上,巨蟒从未收集与循环引用对象,如果他们定义了一个__del__方法 。有一个漂亮的straightforward reason

Python中不会自动收集这样的循环,因为在一般情况下,这是不可能的Python猜测一个安全的顺序运行__del__()方法。

我不愿意说,这是唯一的原因循环引用可达的对象可能不会被发现。可能有一些不寻常的情况可能会阻碍GC的循环检测机制。但是除非你为你的一个物体定义了__del__,你可能可能是好的。请不要担心,如果发现性能问题,请使用GC广泛的调试选项。

+1

嗨。所以从你的回答中,我可以说循环引用可能导致内存泄漏,但通常情况下这并不严重。如果有明显的性能下降,我们应该能够从调试器中得知。鉴于怀疑的好处,对我以前的帖子的回复可能与您的精神是一致的。此外,为了完全避免这个问题,我们可以使用弱引用来引用周期中的一个对象来打破循环引用。 – lightalchemist

1

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

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

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

+5

或使用weakref。 –