我一直在编写一个很长的脚本,偶尔会构建大的dicts和/或列表,我想知道当我使用它们时用del
删除它们是否可以改善性能。或者通常的做法是将这些物品留在周围以便通过垃圾收集来处理?这里的最佳做法是什么?感谢。
答案 0 :(得分:7)
del
不等同于免费(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是垃圾收集。)
现在,如果您使用的名称是list / dict / whatever的 only 名称,则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的一部分。这真的很少见,但这是我遇到的唯一一个我真正想要“删除这个名字”语义的案例。
答案 1 :(得分:1)
del
通常没有必要。
在CPython中,当没有对它们的引用时,对象就会消失。 del
只删除对象的一个引用;如果还有其他对象的引用,它将保持不变,并且del
实际上没有做任何改善你的记忆情况。
相反,只需将变量重新分配给另一个对象(例如,在循环顶部创建一个新的空列表),也最终会少一个对象的引用,隐式地执行与del
相同。如果此时没有对该对象的其他引用,它将立即释放。
还要记住,当函数返回时,局部变量会消失,因此您不需要显式del
在函数中定义的任何名称。
一个例外是循环引用,其中两个(或更多)对象相互引用但实际上没有一个可通过名称访问; Python定期垃圾收集这些,但是如果你在完成对象时打破了圆圈,你可以更快地释放它们。 (这可能只需要一个del
!)但这种情况很有用的情况可能非常罕见。
在IronPyothon(在.NET CLR上运行)或Jython(在JVM上运行)中,最佳内存管理策略可能不同,因为使用了底层VM的垃圾收集器。
答案 2 :(得分:0)
Python的一个优点(与C语言相比)一般来说,您不必担心内存管理的细节,而是可以专注于程序的目的。
所以我的建议是不要打扰,除非你有理由这样做(例如python正在吃你所有的RAM)。