import weakref
import gc
class MyClass(object):
def refer_to(self, thing):
self.refers_to = thing
foo = MyClass()
bar = MyClass()
foo.refer_to(bar)
bar.refer_to(foo)
foo_ref = weakref.ref(foo)
bar_ref = weakref.ref(bar)
del foo
del bar
gc.collect()
print foo_ref()
我希望foo_ref
和bar_ref
分别保留对foo
和bar
的弱引用,只要它们互相引用 * ,但而是打印None
。如何防止垃圾收集器在引用周期内收集某些对象?
bar
应该在此代码中进行垃圾回收,因为它不再是foo
- bar
引用周期的一部分:
baz = MyClass()
baz.refer_to(foo)
foo.refer_to(baz)
gc.collect()
* 我意识到防止循环引用被垃圾收集似乎毫无意义,但我的用例需要它。我有一堆对象以类似Web的方式相互引用,还有一个WeakValueDictionary
,它对一堆中的每个对象保持弱引用。我只希望群中的一个对象在孤立时被垃圾收集,即当群中没有其他对象引用它时。
答案 0 :(得分:2)
通常使用弱引用意味着您无法阻止对象被垃圾回收。
但是,您可以使用一种技巧来防止对象部分参考周期被垃圾回收:在这些上定义__del__()
method。
<强> gc.garbage 强>
收集器发现无法访问但无法释放的对象列表(无法收集的对象)。默认情况下,此列表 仅包含具有
__del__()
方法的对象。有的对象__del__()
方法是参考周期的一部分,导致整个参考周期无法收集,包括对象不一定 在循环中但只能从它到达。 Python不收集这样的 自动循环,因为一般来说,Python不可能 猜测运行__del__()
方法的安全顺序。如果你 知道一个安全的命令,你可以通过检查垃圾来强制解决问题 列表,并明确地打破由于您的对象内的周期 名单。请注意,这些物体即使如此也能保持活力 在垃圾清单中,所以它们也应该从垃圾中删除。 例如,在打破周期后,执行del gc.garbage[:]
清空 名单。通过不创建周期来避免这个问题通常会更好 包含__del__()
方法的对象,可以检查垃圾 在这种情况下,要验证没有创建这样的周期。
如下所示定义MyClass
:
class MyClass(object):
def refer_to(self, thing):
self.refers_to = thing
def __del__(self):
print 'Being deleted now, bye-bye!'
然后您的示例脚本打印:
<__main__.MyClass object at 0x108476a50>
但评论其中一个.refer_to()
来电会导致:
Being deleted now, bye-bye!
Being deleted now, bye-bye!
None
换句话说,通过简单地定义了__del__()
方法,我们阻止了引用循环被垃圾收集,但任何孤立的对象都被删除。
请注意,为了使其正常工作,您需要循环引用;无论如何,对象图中不参考圆的一部分的任何对象都将被拾取。