如何在python列表中立即释放已用内存?

xoshrz7s  于 2022-11-21  发布在  Python
关注(0)|答案(5)|浏览(560)

在许多情况下,您肯定不会再使用该列表,因此希望立即释放内存。

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

我不确定上面的方法是否真的释放了内存。你可以用途:

del a[:]

它实际上删除了列表A中的所有元素。
这是释放记忆的最好方法吗?

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

关于元组和集合,我也有同样的问题。

5ktev3wc

5ktev3wc1#

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

千万不要这样做。Python会自动释放所有不再被引用的对象,所以一个简单的del a确保了如果列表没有被其他地方引用,那么列表的内存也会被释放。如果是这种情况,那么单个列表项也会被释放(以及仅从它们引用的任何对象,依此类推),除非仍引用了某些单独的项。
这意味着只有del a[:]; del a自己释放了多于del a的时候,这个列表被其他地方引用了。这正是你 * 不 * 应该清空列表的时候:别人还在用!!!
基本上,你不应该考虑管理内存块。相反,考虑管理对对象的引用。在99%的Python代码中,Python会在你最后一次需要它之后很快清理掉你不需要的所有东西,而且没有任何问题。每次一个函数完成该函数中的所有局部变量“死亡”时,如果它们指向的对象在其他任何地方都没有被引用,它们将被删除,这将级联到这些对象中包含的所有内容。
只有当你有一个大的物体时,你才需要考虑它(比如说一个巨大的列表),你用它做一些事情,然后你开始一个长期运行的(或者内存密集型)子计算,其中子计算 * 不 * 需要大对象。因为您有对它的引用,直到子计算完成然后你返回时,大对象才会被释放。(且 * 仅 * 是这种情况),您可以在开始子计算之前显式地del您对大对象引用,以便可以更早地释放大对象(如果没有其他人正在使用它;如果调用者将对象传递给您,而调用者在您返回后仍然需要它,您非常**高兴它没有被释放)。

ztmd8pv5

ztmd8pv52#

正如@monkut所指出的,在大多数情况下,你可能不应该太担心内存管理。如果你有一个巨大的列表,你肯定你已经完成了 * 现在 *,它不会离开当前函数的作用域一段时间,但:
del a只是删除你的名字a,如果其他函数或结构或任何东西仍然引用它,它不会被删除;如果这段代码在名称a下有对该列表的唯一引用,并且您使用的是CPython,则引用计数器将立即释放该内存。其他实现(PyPy、Jython、IronPython)可能不会立即杀死它,因为它们有不同的垃圾收集器。
因此,realse_list函数中的del a语句实际上并不执行任何操作,因为调用方仍然有一个引用!
正如您所注意到的,del a[:]将从列表中删除元素,从而可能删除其大部分内存使用。
您可以对集合执行the_set.clear()以获得类似的行为。
由于元组是不可变的,所以你能做的就是del the_tuple,并希望没有其他人引用它--但你可能不应该有巨大的元组!

zrfyljdw

zrfyljdw3#

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的引用计数会增加,正如你所看到的,当你删除列表时,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

它将从内存中释放。

lsmepo6l

lsmepo6l4#

如果你担心内存管理和数据类型的性能,为什么不使用像链接双队列这样的东西呢?
首先,它的内存足迹是分散的,所以你不必马上分配一大块连续的内存。
其次,您将看到入队和出列的访问时间更快,因为与标准列表不同,当您删除中间元素时,不需要在索引中滑动列表的其余部分,这在大型列表中需要时间。
如果你只使用整数,我建议你研究一下二进制堆,因为你会看到O(log^2n)的访问时间,而列表的访问时间大多是O(N)。

sf6xfgos

sf6xfgos5#

如果需要释放list的内存,保留list的名称,只需编写a=[]

相关问题