什么时候python对象是垃圾收集的候选者?

时间:2012-12-03 19:25:27

标签: python object reference garbage-collection

我试图弄清楚究竟什么时候python对象是垃圾收集的候选对象。我已阅读了一些文件/帖子,但未能找到明确的答案。

以下面一行为例。这是foo的最后一个引用。 foo指向的对象何时可用于垃圾回收?

ret = func(['xyz: ' + foo.name])

将其分解为(可能的)个别步骤:

  1. 创建了对名称的临时引用。
  2. ' xyz:'与名称连接并返回值。
  3. 列表是使用新字符串创建的。
  4. 使用新数组调用
  5. 函数。
  6. 函数返回。
  7. 结果已分配给ret。
  8. 下一条指令......
  9. 哪个对象首先有资格被收集?对象的引用计数何时递减?

    如果步骤列表不完整/不正确,请告知我们。我只是试图列举它们,为潜在的参考答案提供一个共同的起点。

2 个答案:

答案 0 :(得分:4)

与其他垃圾收集语言一样,经验法则是:当它无法访问时。这意味着,只要程序(它的任何部分)仍然可以访问它,就不能是gc'd。在那之后,这是公平的比赛。当(甚至是否实际回收时,完全取决于实现。

在您的示例中,名称foo使对象保持活动状态,因为程序仍可在以后的语句中使用它。 (理论上,实现可以检测是否不再使用变量,并删除该引用 - 可能使对象更快到达。实际上,这在Python中是不可能的,除非在JIT编译器编译的某些跟踪中。)列表,相反,如果func在某些可到达的位置(例如,可到达对象的属性或全局变量)中没有存储对它的引用,则在执行func之后或者甚至在它期间可能变得无法访问

请注意,你混淆了foo和它所引用的对象,这在推理垃圾收集时是致命的。没有对象foo,只有foo在给定时间点引用的对象(从而在不同的时间点引用一组对象)。这很重要:

    可以更改
  • foo以引用另一个对象,并且它最初引用的对象可能变得无法访问。除非你区分这两种情况,否则你不能谈论这种情况。
  • 对象foo可能有许多其他引用指向(实际上很可能)。在foo超出范围,被送到del或更改为引用另一个对象后,可能会使对象保持很长时间。

答案 1 :(得分:2)

只要对该变量的所有引用都超出范围或手动删除(del x),该变量就有资格进行垃圾回收。

在您的示例中,foo必须存在于此行之前(否则它是NameError),因此永远不会在您的示例代码块中进行垃圾回收,因为此后引用仍将存在。即使在此之后要调用del foo,我们也必须假定在其他地方没有对该对象的引用,因为它被垃圾收集。