Python列表(元组)中每个元素有多少个字节?
例如,存储一百万个(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并乘以得到实际大小。