我一直在写一个很长的脚本,偶尔构建大的字典和/或列表,我想知道当我完成使用它们时,是否可以通过使用del
删除它们来提高性能。或者把这些对象留在周围,让垃圾收集来处理是正常的做法吗?这里的最佳实践是什么?谢谢。
del
不等于free(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
肯定会使其refcount降为零,因此它将被释放。但是,因为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的一部分。这真的很少见,但这是我遇到的唯一情况,我实际上想要"删除这个名称"的语义。
del
通常是不必要的。
在CPython中,对象在没有引用时消失。del
只删除一个对象引用;如果还有其他对象的引用,它将留在周围,并且del
实际上没有做任何事情来改善您的内存状况。
del
相同的操作。如果此时没有其他对该对象的引用,它将立即被释放。
还要记住,局部变量在函数返回时消失,所以您不需要显式地del
您在函数中定义的任何名称。
一个例外是循环引用,其中两个(或多个)对象相互引用,但实际上没有一个对象可以通过名称访问;Python会周期性地对这些对象进行垃圾收集,但如果在处理完对象后打破循环,则可以更快地释放它们。(这可能只需要一个del
!)不过,这种情况可能非常罕见。
在ironpython(运行在。net CLR上)或Jython(运行在JVM上)中,最佳内存管理策略可能不同,因为使用了底层VM的垃圾收集器。
Python的优点之一(与C等语言相比)是,通常您不必担心内存管理的细节,您可以专注于程序的目的。
所以我的建议是不要打扰,除非你有理由这样做(例如,python正在吃掉你所有的RAM)。