对列表使用 'del
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[:]
这两个语句有什么区别?
3 个回答
1
- 删除的顺序是由具体实现决定的。
- 根据第一个点的回答,是的,它可能会以其他顺序删除(比如先删除元素、随机删除等等),而避免重新分配内存和这个没什么关系。这只是实现选择处理子元素的方式。也许内存分配器会更喜欢释放内存的顺序和分配的顺序相反;但这只是猜测。
del l
是删除变量本身(所以如果没有其他地方引用它,列表也会被删除),而del l[:]
则是把列表中的所有元素都移除。可以试试del l; print l
。
2
其他人已经回答过了。我就简单补充一下我在CPython源代码中发现的内容。
在 listobject.c
文件中的 list_dealloc
函数里,有这样一段注释,正好在开始循环遍历列表中的每个项目之前,用来减少它们的引用计数:
/* 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. */
8
运行 del l
会删除对这个列表的所有引用,所以变量 l 就不复存在了。相反,运行 del l[:]
则是清空列表的内容,这样 l 仍然存在,但变成了一个空列表。
__del__ 方法是在最后一个引用被删除时会运行的。
删除的顺序并没有固定,具体情况取决于实现。当你运行 del l
时,唯一可以保证的是列表 l 及其每个元素的引用计数都会减少1。
在 pypy 中,直到垃圾回收器运行之前,其他事情不会发生。对象被移除的顺序取决于垃圾回收器访问对象的顺序。
在 cpython 中,原作者观察到引用计数的减少是从右到左进行的。当调用 del l[:]
时,减少引用计数的代码是这样的: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