为什么元组比列表占用更少的内存空间?

2024-02-28

A tuple在 Python 中占用更少的内存空间:

>>> a = (1,2,3)
>>> a.__sizeof__()
48

whereas lists 占用更多内存空间:

>>> b = [1,2,3]
>>> b.__sizeof__()
64

Python内存管理内部发生了什么?


我假设您使用的是 64 位 CPython(我在 CPython 2.7 64 位上得到了相同的结果)。其他 Python 实现或者如果您有 32 位 Python,则可能存在差异。

无论实施情况如何,lists 大小可变,而tuples 是固定大小的。

So tuples 可以直接在结构内部存储元素,另一方面,列表需要一个间接层(它存储指向元素的指针)。这一层间接是一个指针,在 64 位系统上是 64 位,因此是 8 个字节。

但还有一件事是lists do:他们过度分配。否则list.append将是一个O(n)手术always- 使其摊销O(1)(快得多!!!)它过度分配。但现在它必须跟踪已分配尺寸和filled size (tuples 只需要存储一种大小,因为分配的大小和填充的大小始终相同)。这意味着每个列表必须存储另一个“大小”,在 64 位系统上是一个 64 位整数,同样是 8 个字节。

So lists 需要至少多 16 个字节的内存tuples。为什么我说“至少”?因为超额分配。过度分配意味着分配了超出需要的空间。但是,过度分配的数量取决于您创建列表和追加/删除历史记录的“方式”:

>>> l = [1,2,3]
>>> l.__sizeof__()
64
>>> l.append(4)  # triggers re-allocation (with over-allocation), because the original list is full
>>> l.__sizeof__()
96

>>> l = []
>>> l.__sizeof__()
40
>>> l.append(1)  # re-allocation with over-allocation
>>> l.__sizeof__()
72
>>> l.append(2)  # no re-alloc
>>> l.append(3)  # no re-alloc
>>> l.__sizeof__()
72
>>> l.append(4)  # still has room, so no over-allocation needed (yet)
>>> l.__sizeof__()
72

Images

我决定创建一些图像来配合上面的解释。也许这些有帮助

在您的示例中,这就是它(示意性地)存储在内存中的方式。我强调了与红色(徒手)循环的差异:

这实际上只是一个近似值,因为int对象也是 Python 对象,CPython 甚至重用小整数,因此内存中对象的更准确表示(尽管不那么可读)可能是:

有用的链接:

  • tuplePython 2.7 的 CPython 存储库中的结构 https://github.com/python/cpython/blob/2.7/Include/tupleobject.h#L24-L32
  • listPython 2.7 的 CPython 存储库中的结构 https://github.com/python/cpython/blob/2.7/Include/listobject.h#L22_L39
  • intPython 2.7 的 CPython 存储库中的结构 https://github.com/python/cpython/blob/2.7/Include/intobject.h#L23-L26

注意__sizeof__并没有真正返回“正确”的尺寸!它仅返回存储值的大小。但是当你使用sys.getsizeof https://docs.python.org/2/library/sys.html#sys.getsizeof结果不同:

>>> import sys
>>> l = [1,2,3]
>>> t = (1, 2, 3)
>>> sys.getsizeof(l)
88
>>> sys.getsizeof(t)
72

有 24 个“额外”字节。这些都是real,这是未计入的垃圾收集器开销__sizeof__方法。这是因为您通常不应该直接使用魔术方法 - 使用知道如何处理它们的函数,在这种情况下:sys.getsizeof https://github.com/python/cpython/blob/2.7/Python/sysmodule.c#L687-L761(实际上增加 GC 开销 https://github.com/python/cpython/blob/2.7/Python/sysmodule.c#L731-L732返回值__sizeof__).

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么元组比列表占用更少的内存空间? 的相关文章

随机推荐