对列表使用 'del

5 投票
3 回答
1242 浏览
提问于 2025-04-17 06:43
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 ldel 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

撰写回答