繁体   English   中英

Python-元组和内存管理

[英]Python - tuples and memory management

在回答与Python有关的问题时,我做了一些试验,发现了与元组有关的东西,但我无法弄清楚:我很难理解为什么空元组比其中包含单个元素的元组要占用更多的空间(根据sys.getsizeof() )。 以下代码已在64位Debian Jessie系统上使用Python 2.7.9的上游版本执行(也已通过Python 3.4.2测试,其中值略有不同,但我正在谈论的总体行为仍然存在):

>> sys.getsizeof(())
56
>> sys.getsizeof((1))
24
>> sys.getsizeof((1,2))
72

如您所见,空元组与单元组有很大的不同(更精确地讲,系数为2.3)。 任何想法在这里发生了什么? 由于元组是递归数据结构,因此我假设sys.getsizeof()返回的值是元组对象本身正在占用的内存量加上对该对象包含的对象的引用(如果元组将元素存储为引用而不是值,则-我不知道)。我最初的想法是像字典中那样在内存中创建具有指定默认大小的元组,该默认大小可以容纳几个元素。 我忘记了空字典为之保留内存的确切元素数量,但这是我用一个小例子表示的意思:

>> sys.getsizeof({})
280
>> sys.getsizeof({"a":0})
280
>> sys.getsizeof({"a":0, "b":1})
280

但是,查看元组似乎没有显示相同的行为,因为在将第一个元素添加到较小的尺寸之后,元组会收缩,然后在添加每个元素的情况下会增长(按预期)。 除此以外,列表似乎没有相同的行为:

>> sys.getsizeof([])
72
>> sys.getsizeof([1])
80
>> sys.getsizeof([1,2])
88

从内存角度来说,空列表要小于一个包含1个或多个元素的列表-完全正常。

我的第二个想法是将单元素元组以某种方式转换为它包含的单个对象,并以某种方式包装所有内容,以便看起来它实际上是一个列表(这就是len()起作用的原因)。 例:

>> sys.getsizeof((1))
24
>> sys.getsizeof(1)
24

这似乎有可能,但是我不相信这确实在发生。

您不是在创建单项元组。 任何表达式都可以用括号括起来而不改变其含义,因此(1)1相同。 要使单个元素成为元组,请写(1,) 当您这样做时,内存消耗应变得更加合理。

但是整数如何需要24个字节? 整数通常最多不是8个字节吗?

在Python 3中,所有整数都是任意精度,甚至在Python 2中,包括整数在内的所有对象都具有一定数量的开销,用于引用计数,类型信息和其他元数据。 对于成熟的Python对象,24字节实际上是相当合理的。

(从技术上讲,小整数是整数,因此在这种特殊情况下可以认为引用计数是不必要的,但是删除它会使解释器的其他部分复杂化,而没有明显的好处。)

在回答的同时,我还想澄清一些事情:

(如果元组将元素存储为引用而不是值-我不知道)

一般来说,Python不允许Python对象实际包含彼此。 在C源代码中,您将看到很多PyObject*变量,但没有PyObject变量。 Python对象生活在堆中,彼此完全独立。 换句话说,是的,元组存储的是引用,而不是实际的对象。

我最初的想法是像字典中的元组一样在内存中创建,具有一定的默认大小,可以容纳几个元素。

没有理由这样做。 元组具有固定的大小。 正式地讲,它们是不可变的,创建后不会更改。 非正式地,可以在C级别上更改它们,但是这些更改不应在Python代码中可见。 您修改元组一旦创建完成后,但你已经使用了任何事情之前,之后你没有再次进行修改。 此外,这些更改实际上不会更改大小,它们只是填充已经存在的阵列插槽。

由于这种不变性,元组没有理由存储比实际更多的元素。 他们不需要支持快速追加或其他尺寸更改操作。

代码(1)不是元组! Python只会将括号视为表达操作优先级的一种方式。 如果要使用元组,则必须至少包含一个逗号。

>>> type(1)
<type 'int'>
>>> type((1))
<type 'int'>
>>> type((1,))
<type 'tuple'>

然后,元组的大小将是其中元素数量的线性函数。

>>> sys.getsizeof(tuple())
28
>>> sys.getsizeof((1,))
32
>>> sys.getsizeof((1,2))
36
>>> sys.getsizeof((1,2,3))
40

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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