Python列表(元组)每个元素占多少字节?
比如,存储一百万个32位整数需要多少内存呢?
alist = range(1000000) # or list(range(1000000)) in Python 3.0
5 个回答
关于“元组”的部分
在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, tupleobject.c
“这要看情况。” Python 在处理列表时,会以一种方式分配空间,以便在往列表中添加元素时,能保持大致恒定的时间效率。
具体来说,当前的实现方式是... 列表总是为一个2的幂次方数量的元素预留空间。所以,当你使用 range(1000000) 时,实际上会分配一个足够容纳 2^20 个元素(大约 104.5 万)的列表。
这只是存储列表结构本身所需的空间(这个结构是一个指向每个元素的 Python 对象的指针数组)。在32位系统中,每个元素需要4个字节,而在64位系统中,每个元素需要8个字节。
此外,你还需要空间来存储实际的元素。这部分的需求差别很大。对于小整数(目前是从-5到256),不需要额外的空间,但对于更大的数字,Python 会为每个整数分配一个新的对象,这样会占用10到100个字节,并且容易导致内存碎片。
总的来说:事情比较复杂,而且 Python 列表不适合存储大型的同类数据结构。如果你需要这样做,可以使用 array
模块,或者如果需要进行向量化运算,可以使用 NumPy。
另外,元组与列表不同,它们并不是为了逐渐添加元素而设计的。我不知道分配器是怎么工作的,但别想用它来处理大型数据结构 :-)
有用的链接:
不过这些链接并没有给出明确的答案。可以尝试以下方法:
使用操作系统工具,测量Python解释器在有/没有列表时消耗的内存。
使用一个第三方扩展模块,这个模块可以定义某种方式来获取PyObject的大小。
更新:
import asizeof
N = 1000000
print asizeof.asizeof(range(N)) / N
# -> 20 (python 2.5, WinXP, 32-bit Linux)
# -> 33 (64-bit Linux)