Python中定期删除长字典/列表是一个好的编程习惯吗?

7

我一直在写一个长脚本,有时会构建大的字典和/或列表,我想知道是否可以通过使用del删除它们来提高性能,当我完成使用它们后。或者留下这些对象让垃圾回收来处理是正常做法吗?这里应该采取什么最佳实践?谢谢。


如果我没记错的话,从列表/字典中删除值只会将这些值释放给垃圾回收器并停止在列表/字典中引用它们,因此实际上您仍然需要处理所有这些内存,只是被分成了小块。不过我可能错了,我还没有对Python的垃圾回收进行深入研究。 - Aren
1
在CPython中,如果它们超出范围,它们将被收集(除了循环引用)。从您的问题中也不清楚您是指删除列表成员还是整个列表... - Fredrik Håård
3个回答

11

delfree(3)不等同。它并不能强制Python释放内存。它可能根本没有释放内存。您应该完全避免将其与内存使用关联在一起。

del唯一做的是从其作用域中删除一个名称。(或者从集合中删除一个项目,或者删除一个属性。但我认为这不是您在这里讨论的内容。)

实际上,这个:

del foo

等价于这个:

del LOCAL_SCOPE['foo']
所以这并不会释放任何内存:
massive_list = list(range(1000000))
same_massive_list = massive_list
del massive_list

因为它只是删除了名称massive_list,而底层对象仍然有另一个名称same_massive_list,因此它并没有消失。 del不是控制Python内存管理的秘密钩子; 它只是请求Python触发其内存管理的几种方法之一。

(顺便说一下,CPython是引用计数+循环收集,而不是垃圾回收。 只要最后一个对它们的引用消失,对象就会立即释放。 垃圾不会等待被清除。 当然,其他实现的情况可能不同; 例如PyPy进行垃圾回收。)

现在,如果您使用的名称是列表/字典/任何东西的唯一名称,则del肯定会导致其引用计数降为零,从而释放它。 但是,由于del的语义实际上是关于删除名称的,因此在这种情况下我不会使用它。 我会让变量超出范围(如果可行),或将名称重新分配给空列表、None或对您的程序有意义的任何内容。 您甚至可以原地清空列表,即使有多个名称指向同一列表也可以工作:

foo = list(range(1000000))
bar = foo
foo[:] = []
# Both `bar` and `foo` still refer to the original list, but now it's empty

你可以使用d.clear()来清空字典。

我只会在类或模块作用域中使用del来处理变量,这时我只是临时需要一些辅助值,但真的真的不想将其公开为API的一部分。虽然这种情况非常罕见,但这是我遇到的唯一一种实际上需要"删除这个变量名"语义的情况。


喜欢这个答案,特别是关于清空容器的那一部分。 - kindall
我认为 del foo[:] 更加简洁。 - nneonneo
我喜欢只将 del 用于删除名称。列表和字典都有 .pop,而列表有切片语法,因此几乎不需要特殊的构造;只有使用 del 才能删除变量(大概)。这也避免了扫描问题:当你看到 del super_duper_long_name[2] 时,直到读到行末,你才能确定它是哪种类型的 del - Eevee

3

del通常是不必要的。

在CPython中,当没有引用指向对象时,对象会被删除。 del仅删除对对象的一个引用;如果仍然有其他引用指向该对象,则它将保留,并且del实际上没有做任何事情来改善您的内存情况。

相反,仅将变量重新分配给另一个对象(例如,在循环的顶部创建一个新的空列表)也将导致对该对象的一个引用减少,隐式地执行与del相同的操作。如果此时没有其他引用指向该对象,则它将立即被释放。

还要记住,当函数返回时,局部变量会被删除,因此您不需要显式地del在函数中定义的任何名称。

例外情况是循环引用,其中两个(或多个)对象彼此引用,但通过名称实际上无法访问任何一个对象;Python定期进行垃圾回收,但如果您完成对象后打破循环,则可以更快地释放它们。 (这可能只需要一个del!)然而,这种情况实用的情况可能非常罕见。

在IronPyothon(运行在.NET CLR上)或Jython(运行在JVM上)中,最佳的内存管理策略可能会有所不同,因为使用底层VM的垃圾回收器。


0
Python相对于像C这样的语言的优势之一是,通常情况下你不必担心内存管理的细节,可以集中精力于程序的目的。因此,我的建议是,除非你有理由这样做(例如Python正在消耗所有的RAM),否则不要费心。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接