[英]Does casting a list into tuple result in tuple having memory overhead?
让我们创建一个列表列表:
l = []
for i in range(1000000):
l.append(['abcdefghijklmnopqrstuvwxyz', '1.8', '5', 'john@email.com', 'ffffffffff'])
l.__sizeof__()
报告8697440
, 进程占用111 MB
。
现在让我们尝试使用元组列表而不是列表列表:
l = []
for i in range(1000000):
l.append(('abcdefghijklmnopqrstuvwxyz', '1.8', '5', 'john@email.com', 'ffffffffff'))
l.__sizeof__()
报告8697440
, 进程占用12 MB
。
如预期的那样,巨大的进步。 现在让我们在插入之前将列表转换为元组:
l = []
for i in range(1000000):
l.append(tuple(['abcdefghijklmnopqrstuvwxyz', '1.8', '5', 'john@email.com', 'ffffffffff']))
l.__sizeof__()
报告8697440
, 进程占用97 MB
。
为什么是97 MB,而不是12 MB?
是垃圾吗? gc.collect()
报告0
。
做一个del l
释放所有内存降到4 MB
,这只是一个小过一下空白解释占据。 所以, l
实际上是肿的。
当我们将列表转换为元组时,与从头开始创建的元组相比,生成的元组是否“不纯正”?
如果是这样,是否有解决方法将列表转换为“纯”元组?
不会。您的推理方法存在缺陷,因为您没有意识到tuple
使用常量折叠 。
(提示:元组无法容纳12MB的内容,而列表却不能容纳111MB的内容!)
您的第一个示例将创建一百万个列表。 第三个示例创建一个列表和一百万个元组。 轻微的内存差异是由于元组的存储更为紧凑(例如,它们没有任何额外的容量来处理追加)。
但是在第二个示例中,您有一个列表和一个元组-这是一个常量值,因此在代码编译期间会创建一次,并且在设置列表的每个元素时都将重用对该对象的引用。 如果它不是恒定的(例如,如果您将i
用作元组的元素之一),则每次都必须创建一个新的元组,并且您将获得与示例3相当的内存使用率。
第三个示例在理论上可以与#2具有相同的内存使用量,但是这将要求Python将每个新创建的元组与所有现有元组进行比较,以查看它们是否完全相同。 这将很慢,并且在不会创建大量相同元组的典型实际程序中,其收益极为有限。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.