58

我想检查 python 中 int 数据类型的大小:

import sys
sys.getsizeof(int)

结果是“436”,这对我来说没有意义。无论如何,我想知道我的机器上有多少字节(2,4,..?) int 。

4

1 回答 1

124

简短的回答

您得到的是的大小,而不是类的实例。调用int以获取实例的大小:

>>> sys.getsizeof(int())
24

如果那个尺寸看起来还是有点大,请记住 Python与in(例如)cint非常不同。int在 Python 中,anint是一个成熟的对象。这意味着有额外的开销。

除了其他存储之外,每个 Python 对象都至少包含一个引用计数和对该对象类型的引用;在 64 位机器上,占用 16 个字节!内部int结构(由标准 CPython 实现决定)也随着时间而改变,因此占用的额外存储量取决于您的版本。

int关于Python 2 和 3 中对象的一些细节

这是 Python 2 中的情况。(其中一些改编自Laurent Luce的博客文章)。整数对象表示为具有以下结构的内存块:

typedef struct {
    PyObject_HEAD
    long ob_ival;
} PyIntObject;

PyObject_HEAD是定义引用计数和对象类型的存储的宏。文档中对其进行了一些详细的描述,并且可以在答案中看到代码。

内存分配在大块中,因此每个新整数都没有分配瓶颈。该块的结构如下所示:

struct _intblock {
    struct _intblock *next;
    PyIntObject objects[N_INTOBJECTS];
};
typedef struct _intblock PyIntBlock;

这些一开始都是空的。然后,每次创建一个新整数时,Python 都会使用 所指向的内存next并递增next以指向块中的下一个空闲整数对象。

我不完全确定一旦超过普通整数的存储容量,这种情况会如何变化,但是一旦这样做,a 的大小int就会变大。在我的机器上,在 Python 2 中:

>>> sys.getsizeof(0)
24
>>> sys.getsizeof(1)
24
>>> sys.getsizeof(2 ** 62)
24
>>> sys.getsizeof(2 ** 63)
36

在 Python 3 中,我认为总体情况是一样的,但整数的大小以更零碎的方式增加:

>>> sys.getsizeof(0)
24
>>> sys.getsizeof(1)
28
>>> sys.getsizeof(2 ** 30 - 1)
28
>>> sys.getsizeof(2 ** 30)
32
>>> sys.getsizeof(2 ** 60 - 1)
32
>>> sys.getsizeof(2 ** 60)
36

当然,这些结果都取决于硬件!YMMV。

Python 3 中整数大小的可变性暗示它们可能更像可变长度类型(如列表)。事实上,事实证明这是真的。这是Python 3中对象的C定义:structint

struct _longobject {
    PyObject_VAR_HEAD
    digit ob_digit[1];
};

该定义附带的注释总结了 Python 3 的整数表示。零不是由存储的值表示,而是由大小为零的对象表示(这就是为什么sys.getsizeof(0)is 24bytes 而sys.getsizeof(1)is 28)。负数由具有负大小属性的对象表示!太奇怪了。

于 2012-04-28T17:00:54.380 回答