什么时候回收值垃圾收集?

时间:2013-07-14 14:22:26

标签: python garbage-collection

我正在尝试理解Python垃圾收集器的功能,以及是否可以执行任何操作来控制何时收集对象。我写了这个测试:

>>> class Test:
...     def __del__(self):
...         print 'Delete ' + str(self)
...
>>> def fun():
...    return Test()
...
>>> fun()
<__main__.Test instance at 0x0000000002989E48>
>>> fun()
Delete <__main__.Test instance at 0x0000000002989E48>
<__main__.Test instance at 0x00000000023E2488>
>>> fun()
Delete <__main__.Test instance at 0x00000000023E2488>
<__main__.Test instance at 0x0000000002989C48>

正如您所看到的,Test实例虽然我没有保留实例,但在下次调用fun之前不会被删除。这只是一次意外(可能是在任何其他地方被删除),还是只有在我再次呼叫fun时才删除它的具体原因?如果我不保留对它的引用,我能做些什么来确保它被删除?

2 个答案:

答案 0 :(得分:1)

尝试在返回值上显式调用del

returned_value = fun()
del returned_value

但像__del__这样的终结者可能会有问题;正如你已经看到的那样,一个问题是当他们被召唤时不是确定性的。此外,在终结器中可以重新实例化已删除的对象,例如在全局列表中粘贴对它的引用。

如果您需要释放资源(除了原始内存) - 解锁,关闭文件或释放数据库连接之类的东西,请使用上下文管理器,并使用with语句限制其生命周期。其中许多资源已经是上下文管理器。例如,可以使用with

隐式锁定和解锁threading.Lock
# "with" statement will call the __enter__ method of self.lock,
# which will block until self.lock can be locked
with self.lock:
    # do thread-synchronized stuff here

# self.lock is automatically released here - at then end of
# the "with" block, the lock's __exit__ method is called, which
# releases the lock. This will get called even if the block is 
# exited by a raised exception

答案 1 :(得分:1)

Python垃圾收集器(与所有垃圾收集器一样)的“联系人”是它会在最后一次可到达的引用消失后的某个时间释放一个对象。

因为CPython使用引用计数,作为一个实现细节,它将在最后一次可达的引用消失后立即释放大多数垃圾对象(特别是非循环对象) 。这不是Python语言的保证,并且不适用于其他Python实现,如PyPy,Jython,IronPython,所以依赖它通常被认为是不好的做法。

在你的情况下,你在再次调用函数后收集的对象所观察到的与垃圾收集器的行为几乎没有关系,而是由于交互式解释器shell的工作方式。

在交互式提示中评估表达式时,结果值会自动保存在变量_中,因此如果您发现在之后仍然只需,则可以将其恢复>你看过它了。因此,在fun()来电之后, 仍然是对返回值的引用。然后当你评估另一个表达式(任何 else,它不必再次涉及fun)时,_会被新值覆盖,允许旧值垃圾收集。

适用于在交互式提示下直接输入的表达式,因此它不会延迟函数内的对象集合,也不会延迟导入Python代码或作为脚本运行。