繁体   English   中英

将列表强制转换为元组会导致元组有内存开销吗?

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM