39

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

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

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

del a[:]

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

所以最好的释放方式是这样吗?

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

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

顺便说一句,元组和集合怎么样?

4

5 回答 5

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

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

这意味着唯一del a[:]; del a会发布更多内容的时间del a是在其他地方引用列表时。这正是应该清空列表的时候:其他人仍在使用它!!!

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

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

于 2012-09-14T03:19:02.733 回答
7

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

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

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

del a[:]正如您所注意到的,将从列表中删除元素,因此可能会删除大部分内存使用。

您可以the_set.clear()使用集合来实现类似的行为。

你可以对元组做的所有事情,因为它们是不可变的,del the_tuple希望没有其他人引用它——但你可能不应该有巨大的元组!

于 2012-09-14T03:00:25.987 回答
6

Python 使用引用计数来管理其资源。

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 = None # or
del a

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

sys.getrefcount(b) # gives 2

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

b = None

它将从内存中释放出来。

于 2012-09-14T03:56:00.170 回答
2

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

首先,它的内存占用分散在内存之外,因此您不必立即分配大量连续内存。

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

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

于 2012-09-14T03:47:54.293 回答
0

如果您需要释放列表的内存,保留列表的名称,您可以简单地写a=[]

于 2020-05-24T16:45:55.130 回答