如何在python列表中立即释放使用过的内存?

时间:2012-09-14 02:51:31

标签: python

在很多情况下,你确定你肯定不会再次使用该列表,我希望现在应该释放内存

a = [11,22,34,567,9999]
del a

我不确定它是否真的释放了内存,你可以使用

del a[:]

实际上删除了列表a中的所有元素。

所以最好的发布方式是这个吗?

def realse_list(a):
   del a[:]
   del a

不太确定。需要你的意见。

顺便说一下,元组和套装怎么样?

5 个答案:

答案 0 :(得分:29)

def release_list(a):
   del a[:]
   del a

不要永远这样做。 Python会自动释放所有未被引用的对象,因此如果列表未在其他任何地方引用,则简单del a可确保释放列表的内存。如果是这种情况,那么单个列表项也将被释放(以及仅从它们引用的任何对象,依此类推等),除非仍然引用了一些单独的项目。

这意味着当del a[:]; del a在其他地方引用列表时,del a将自行释放超过del唯一时间。当不应清空列表时,正好:其他人仍在使用它!

基本上,你不应该考虑管理内存。相反,考虑管理对象的引用。在99%的Python代码中,Python会在您上次需要它之后很快清理掉您不需要的所有内容,并且没有问题。每次函数完成该函数中的所有局部变量“die”时,如果它们指向未在其他任何地方引用的对象,它们将被删除,并且将级联到这些对象中包含的所有内容。

你需要考虑它的唯一一次是当你有一个大对象(比如一个巨大的列表)时,你用它做一些事情,然后你开始一个长时间运行(或内存密集)的子计算,其中子计算需要大对象 。因为您有对它的引用,所以在子计算完成然后返回之前,不会释放大对象。在那种情况下(并且那种情况),您可以在开始子计算之前显式{{1}}对大对象的引用,以便大对象可以是之前被释放(如果没有其他人正在使用它;如果调用者将对象传递给您,并且调用者确实在您返回后仍然需要它,那么您将非常很高兴它没有被释放。)

答案 1 :(得分:5)

正如@monkut所说,在大多数情况下,你可能不应该过多担心内存管理。如果你确实有一个巨大的列表,你肯定已经完成了现在,但它暂时不会超出当前函数的范围,但是:

del a只会删除您的名称a以获取该内存块。如果某些其他功能或结构或其他任何引用仍然存在,则不会被删除;如果此代码仅在名称a下具有对该列表的引用,并且您正在使用CPython,则引用计数器将立即释放该内存。其他实现(PyPy,Jython,IronPython)可能不会立即杀死它,因为它们有不同的垃圾收集器。

因此,del a函数中的realse_list语句实际上并没有做任何事情,因为调用者仍然有引用!

正如您所注意的,

del a[:]将从列表中删除元素,从而可能大部分内存使用。

您可以the_set.clear()执行与集类似的行为。

所有你可以用元组做的,因为它们是不可变的,是del the_tuple并希望没有其他人可以参考它 - 但你可能不应该有巨大的元组!

答案 2 :(得分:3)

Python使用Reference Count来管理其资源。

import sys
class foo:
    pass

b = foo()
a = [b, 1]

sys.getrefcount(b)  # gives 3
sys.getrefcount(a)  # gives 2

a = None  # delete the list
sys.getrefcount(b)  # gives 2

在上面的例子中,当你把它放入一个列表时,b的引用计数会增加,正如你所看到的,当你删除列表时,b的引用计数也会减少。所以在你的代码中

def release_list(a):
   del a[:]
   del a

多余。

总之,您需要做的就是将列表分配到None对象或使用del关键字从属性字典中删除列表。 (a.k.a,解除实际对象的名称)。例如,

a = None # or
del a

当对象的引用计数变为零时,python将为您释放内存。要确保删除对象,必须确保没有其他地方按名称或容器引用对象。

sys.getrefcount(b) # gives 2

如果sys.getrefcount给你2,那意味着你是唯一拥有对象引用的人,当你做

b = None

它将从内存中释放出来。

答案 3 :(得分:2)

如果您担心数据类型的内存管理和性能,为什么不使用类似链接的双队列。

首先,它的内存占用空间分散在内存中,因此您无需立即分配大量连续内存。

其次,您将看到更快的入队和出队访问时间,因为与标准列表不同,当您删除时,可以说中间元素不需要在索引中滑动列表的其余部分,这在大型列表中需要时间。

我还应该注意,如果你只使用整数,我会建议查看二进制堆,因为你会看到O(log ^ 2n)访问时间,而主要是O(N)和列表。

答案 4 :(得分:0)

如果您需要释放列表的内存并保留列表名称,则只需写a=[]