Python列表(元组)中每个元素有多少个字节?

时间:2020-03-06 14:44:45  来源:igfitidea点击:

例如,存储一百万个(32位)整数列表需要多少内存?

alist = range(1000000) # or list(range(1000000)) in Python 3.0

解决方案

"这取决于。" Python为列表分配空间的方式是,实现将元素添加到列表的摊销固定时间。

实际上,当前实现的含义是...列表中始终为2的幂的元素分配了空间。因此range(1000000)实际上将分配一个足以容纳2 ^ 20个元素(约10.45百万个)的列表。

这只是存储列表结构本身(这是指向每个元素的Python对象的指针的数组)所需的空间。 32位系统将每个元素需要4个字节,而64位系统将每个元素使用8个字节。

此外,我们需要空间来存储实际元素。这千差万别。对于较小的整数(当前为-5到256),不需要额外的空间,但是对于较大的整数,Python为每个整数分配一个新的对象,该对象占用10-100个字节,并倾向于将内存碎片化。

底线:这很复杂,Python列表不是存储大型同类数据结构的好方法。为此,请使用"数组"模块;或者,如果需要进行矢量化数学,请使用NumPy。

与列表不同,PSTuples并非设计为将元素逐渐添加到它们。我不知道分配器的工作原理,但甚至不考虑将其用于大型数据结构:-)

我很确定这是特定于实现的。当然,这取决于整数的内部表示形式,我们不能假设它们将被存储为32位,因为Python为我们提供了任意大的整数,因此较小的int可以更紧凑地存储。

在我的Python(Core 2 duo上的Fedora 9上为2.5.1)上,分配前的VmSize为6896kB,之后为22684kB。再分配一百万个元素后,VmSize达到38340kB。对于1000000个整数,这非常明显地表示大约16000kB,每个整数大约16个字节。这表明该列表的开销很大。我会用一大撮盐来计算这些数字。

有用的链接:

如何获取python对象的内存大小/用法

python对象的内存大小?

如果将数据放入字典中,我们如何计算数据大小?

但是,他们没有给出明确的答案。要走的路:

  • 使用/不使用列表来测量Python解释器消耗的内存(使用OS工具)。
  • 使用定义某些sizeof(PyObject)的第三方扩展模块。

更新:

配方546530:Python对象的大小(已修订)

import asizeof

N = 1000000
print asizeof.asizeof(range(N)) / N
# -> 20 (python 2.5, WinXP, 32-bit Linux)
# -> 33 (64-bit Linux)

解决问题的"元组"部分

在典型的构建配置中声明CPython的PyTuple可以归结为:

struct PyTuple {
  size_t refcount; // tuple's reference count
  typeobject *type; // tuple type object
  size_t n_items; // number of items in tuple
  PyObject *items[1]; // contains space for n_items elements
};

PyTuple实例的大小在其构造过程中是固定的,此后无法更改。 PyTuple占用的字节数可以计算为

sizeof(size_t) x 2 + sizeof(void*) x (n_items + 1).

这使元组的大小变浅。为了获得完整的大小,我们还需要添加植根于" PyTuple :: items []"数组中的对象图所消耗的字节总数。

值得注意的是,元组构造例程确保仅创建空元组的单个实例(单例)。

参考:
Python.h,
object.h,
tupleobject.h,
元组对象

A new function, getsizeof(), takes a
  Python object and returns the amount
  of memory used by the object, measured
  in bytes. Built-in objects return
  correct results; third-party
  extensions may not, but can define a
  __sizeof__() method to return the object’s size.
kveretennicov@nosignal:~/py/r26rc2$ ./python
Python 2.6rc2 (r26rc2:66712, Sep  2 2008, 13:11:55) 
[GCC 4.2.3 (Ubuntu 4.2.3-2ubuntu7)] on linux2
>>> import sys
>>> sys.getsizeof(range(1000000))
4000032
>>> sys.getsizeof(tuple(range(1000000)))
4000024

显然,返回的数字不包含所包含对象消耗的内存(sys.getsizeof(1)== 12)。

我对你为什么要问保持警惕。我们是否要找出给定实现所需的内存量?假设我们要阅读10,000,000个小部件,并想知道它将吸收多少RAM?

在这种情况下,与其尝试找出每个小部件占用多少RAM,不如计算出10,000个小部件需要占用多少RAM并乘以得到实际大小。