class ToBeDeleted:
def __init__(self, value):
self.value = val
# Whatever...
def __del__(self):
print self.value
l = [ToBeDeleted(i) for i in range(3)]
del l
这会打印2, 1, 0
。
现在,已删除元素的顺序是在规范中定义的,还是特定于实现的? (或者我可能不理解底层的机制)
例如,输出可能是0, 1, 2
吗? 我意识到2, 1, 0
顺序可能是为了避免在删除元素时重新分配元素,但问题仍然存在。
最后一项 - del l
和del l[:]
陈述之间的区别是什么?
答案 0 :(得分:8)
运行del l
将删除对列表的任何引用,因此符号 l 将消失。相反,运行del l[:]
会删除列表中的内容,将 l 保留为空列表。
__del__方法是在销毁实例的最后一个引用时运行的方法。
未指定删除顺序,并且是特定于实现的。当您运行del l
时,唯一可以保证的是列表 l 的引用计数及其每个元素将减少一个。
使用 pypy ,在运行垃圾收集器之前不会发生任何其他事情。对象删除的顺序取决于GC访问对象的顺序。
在 cpython 中,OP在观察到从右到左发生参考递减时是正确的。在此处调用del l[:]
时,用于递减refcounts的代码为:http://hg.python.org/cpython/file/2.7/Objects/listobject.c#l700。调用del l
时,类似的代码用于递减引用:http://hg.python.org/cpython/file/2.7/Objects/listobject.c#l596
答案 1 :(得分:2)
其他人已经回答了。我将添加我在CPython源代码中找到的内容。
list_dealloc
文件中的listobject.c
函数在循环列表项之前立即包含此注释,以减少其引用计数:
/* Do it backwards, for Christian Tismer.
There's a simple test case where somehow this reduces
thrashing when a *very* large list is created and
immediately deleted. */
答案 2 :(得分:1)
del l
删除变量本身(因此列表,如果没有别的东西保留它),而del l[:]
删除列表中的所有元素。试试del l; print l
。