python会自动垃圾收集双链表吗?
作者:互联网
参见英文答案 > Does Python GC deal with reference-cycles like this? 4个
背景
我有一个树形结构.在这个树结构中,我将节点的孩子保持为双向链表:
(来源:Doubly linked list)
(由于创建此列表的广度优先搜索方法,我选择了此结构.)
问题
现在我担心的是垃圾收集器是否可以自动销毁此列表.当然,我只保留对这三者的根节点的引用. Afaik GC的原理是它收集内存中的数据结构,其中没有指向任何引用.但是在双向链表中,每个节点都是从它的兄弟节点引用的,兄弟节点引用节点.因此总是会引用一个节点,GC永远不会收集它.
垃圾收集器会处理双向链表吗?
如果没有,最简单的收集方式是什么?
相关问题:
Why does Lua use a garbage collector instead of reference counting?
Python: Memory usage and optimization when modifying lists
解决方法:
每个Python实现都有不同的垃圾收集方案.通用答案是“是的,如果它是垃圾,它应该是垃圾收集.”但是你可能想要比这更具体的东西.
在CPython中,垃圾收集使用引用计数和循环收集器.如果对象的引用计数降为0,则会清除它.但是在你的情况下,当你的列表的所有外部引用都消失了,仍然会有内部引用,所以refcounting本身并不能解决你的问题.这就是循环收集器的用途.
假设您的节点没有__del__方法,并且您没有(直接或间接)禁用“补充垃圾收集”(默认情况下它已启用),循环收集器将检测到您的节点都相互引用,但没有其他任何引用他们,并清理它. (这可能需要两次通过,因为它使用世代系统.)
您可以使用gc模块显式运行循环收集器(gc.collect())而不是等待它,或者检查它正在做什么.例如,如果您这样做:
gc.collect()
oldcounts = gc.get_counts()
del last_reference_to_list
gc.collect()
newcounts = gc.get_counts()
print(oldcounts, newcounts)
…你应该能够告诉你(没有完美的可靠性,但是足够用于学习和测试目的)你的节点都已经消失了.
如果你的节点有__del__方法怎么办?然后你必须给GC一些帮助.您需要做的是使用__del__方法打破包含对象的任何循环.如果在列表之间没有任何节点共享,那么显而易见的方法就是遍历列表并删除前向和后向指针. (从技术上讲,你只需要del或者其中一个,但你也可以这两个.)如果你需要节点上的__del__方法,你可能需要在顶层dl_list(或tree_node或者它是什么)拥有这些),所以这是一个显而易见的地方.
当然,如果你不需要__del__方法,那么有一个更简单的解决方案:摆脱它.
最后一种可能性是使用weakref
作为反向链接,但是使用前向链接的常规参考.这样,就没有可能的周期.但是你必须要小心添加和删除节点,以确保你永远不会暂时离开节点,只有一个弱参数.
如果您正在使用Jython或IronPython,则垃圾收集与底层运行时(JVM或.NET)相关联,因此您必须阅读相应的文档.
PyPy有自己的垃圾收集器(实际上,可以选择不同的选项),你可以阅读关于here.
如果您使用的是不太常见的实现,则应该有类似的文档可用.
标签:doubly-linked-list,python,garbage-collection 来源: https://codeday.me/bug/20190723/1508957.html