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

40 人关注

在很多情况下,你肯定不会再使用这个名单,我希望现在就能释放内存。

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

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

del a[:]

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

那么,最好的释放方式是这样的?

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

not quite sure.need your opinion.

btw, tuple和set怎么样?

1 个评论
除非你正在处理大量的数据,并且确实得到了MemoryError异常,否则不要担心内存管理问题。
python
Max
Max
发布于 2012-09-14
5 个回答
Ben
Ben
发布于 2020-05-25
已采纳
0 人赞同
def release_list(a):
   del a[:]
   del a

Do not ever这样做。Python 会自动释放所有不再被引用的对象,所以一个简单的 del a 可以确保如果列表没有被其他地方引用,列表的内存将被释放。如果是这样,那么各个列表项也将被释放 (以及任何只被它们引用的对象,等等,等等),除非一些单独的项也仍然被引用。

这意味着onlydel a[:]; del a会比del a自己释放更多的时候,是在列表被其他地方引用的时候。这就是precisely when you shouldn't be emptying out the list: someone else is still using it!!!

基本上,你不应该考虑管理内存的碎片。相反,考虑管理对对象的引用。在99%的Python代码中,Python在你最后一次需要它之后很快就会清理你不需要的东西,而且没有任何问题。每次函数结束时,该函数中的所有局部变量都会 "死亡",如果它们指向没有被其他地方引用的对象,它们就会被删除,这将连带影响到这些对象中包含的所有东西。

你唯一需要考虑的是,当你有一个大对象(比如说一个巨大的列表),你对它做了一些事情,然后你开始一个长期运行(或内存密集)的子计算,其中大对象isn't子计算所需要的。因为你有一个对它的引用,这个大对象不会被释放,直到子计算结束,然后你返回。在这种情况下(以及only这种情况下),你可以在开始子计算之前明确地del你对大对象的引用,这样大对象就可以提前被释放(如果没有人在使用它;如果调用者把对象传给你,而调用者does在你回来后仍然需要它,你将是very很高兴它没有被释放)。

那如果 a 是一个成员变量(一个大变量),而且我知道我不会再使用它,这算不算是一个 "引用变量"? 情形很简单。我有一个对象,处理一个大列表 when_needed .在某些方法被调用后, a 列表进行处理,我对结果进行缓存。在这种情况下,我知道我永远不需要 a 不再是了。
Ben
@hsgubert 如果 a 是某个对象的属性(成员变量),那么是的,它是通过作为该对象的一部分而被引用的(假设该对象本身在某处被引用)。但是如果你知道你不再需要它,并且你在同一个类的一个方法中,你可以直接 del self.a 来摆脱它。如果你不在那个类的方法中,就不要去搞它。好的设计几乎总是让每个类负责管理自己的属性;如果一个类 other 程序的某些部分可以随机地决定该对象不再需要它的一个属性了。
Danica
Danica
发布于 2020-05-25
0 人赞同

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

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

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

替换代码5】正如你所注意到的,将从列表中移除元素,因此可能会占用大部分的内存。

你可以做 the_set.clear() ,以获得与集合类似的行为。

因为元组是不可变的,所以你能做的就是 del the_tuple ,并希望没有其他人对它有一个引用--但你可能不应该有巨大的元组!"。

如果对薄弱的参考资料进行讨论,这个答案将大大地更完整。
Shao-Chuan Wang
Shao-Chuan Wang
发布于 2020-05-25
0 人赞同

Python uses Reference Count 来管理其资源。

import sys
class foo:
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

是多余的。

总之,你需要做的是将列表分配到一个无对象中,或者使用del关键字从属性字典中删除列表。(a.k.a,从实际对象中解除名称的绑定)。比如说。

a = None # or
del a

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

sys.getrefcount(b) # gives 2

If sys.getrefcount给你2,这意味着你是唯一拥有该对象引用的人,当你做了

b = None

it will get freed from the memory.

Bob
Bob
发布于 2020-05-25
0 人赞同

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

首先,它的内存足迹分散在整个内存中,所以你不必一开始就分配一大块连续的内存。