如何截断python中的列表?并且分配新的列表()会导致内存泄漏吗?

时间:2013-06-15 08:10:22

标签: python list

假设我在python中有一个相当大的列表my_list,我想截断它。我可以通过删除它或为my_list分配新列表来实现它。什么是更好的方法?

my_list = range(1, 10000)

方法1:

my_list = list() 
print len(my_list) # prints 0

方法2:

del my_list[:] 
print len(my_list) # prints 0

我觉得方法2更适合这样做,我是对的吗?

2 个答案:

答案 0 :(得分:6)

在内部,Python使用一种名为reference counting的机制来跟踪数据是否仍然可访问。每当新的“变量”引用数据时,数据的引用计数器就会增加。每当“变量”停止引用数据时,数据的引用计数器就会递减。当引用计数器达到0时,数据将被删除(调用其“释放函数”):http://docs.python.org/2/c-api/refcounting.html

例如,这会创建一个“大”列表,几乎在创建后立即删除,因为没有变量来“增加”其引用计数器:

range(1, 10000)

这会创建一个新列表,允许您通过my_list引用它并将列表的引用计数器设置为“1”

my_list = range(1, 10000)

编写以下语句,现在将减少列表的引用计数器。假设您没有其他引用,该计数器达到0,因此列表将被删除。

my_list = None

最后一个例子:

my_list = range(1, 10000)
del my_list[:]

这个创建10000个项目的列表。使用参考计数器“1”。第二个语句删除列表中的10000个项目 - 但您仍然有一个对空列表的引用。你看到了区别吗?


BTW,引用计数是一种很好的自动释放机制,它具有确定性(与Java垃圾收集器相反)的好处。 但是,有一种情况是引用计数不起作用:如果你有循环依赖。对象A引用引用对象A的对象B.在这种情况下,只要“圆圈”没有被破坏,A或B引用计数器都不能达到0。但我认为这超出了你的问题。无论如何,对于那些包含非主控循环依赖的程序,Python有一个optional garbage collector来释放这样的循环。默认情况下启用垃圾收集器。这很容易检查:

>>> import gc
>>> gc.isenabled()
True

作为最后一点,即使垃圾收集器也是有限的,因为它不会释放包含终结器(__del__)的对象的循环。有关http://arctrix.com/nas/python/gc/

的理由,请参阅以下链接

答案 1 :(得分:1)

删除是我喜欢的,因为这两个操作几乎同时进行。并且del清除与列表关联的任何内存引用,并将其分配给新列表可能会导致旧内存无法正确清除。