Skip to main content
 首页 » 编程设计

python之如何在 python 中截断列表分配一个新的 list() 会导致内存泄漏吗

2025年05月04日16me-sa

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

my_list = range(1, 10000) 

方法一:

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

方法二:

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

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

请您参考如下方法:

在内部,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 项——但您仍然有一个对空列表的引用。你看出区别了吗?


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

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

最后要注意的是,即使是垃圾收集器也是有限的,因为它不会释放包含带有终结器 (__del__) 的对象的循环。有关此 http://arctrix.com/nas/python/gc/ 的合理性,请参阅以下链接