“sys.getsizeof(int)”返回一个不合理的大值?
- 2025-02-25 09:07:00
- admin 原创
- 24
问题描述:
我想检查 python 中 int 数据类型的大小:
import sys
sys.getsizeof(int)
结果是“436”,这对我来说毫无意义。无论如何,我想知道 int 在我的计算机上占用多少字节(2,4,..?)。
解决方案 1:
简短的回答
您获取的是类的大小,而不是类实例的大小。调用int
以获取实例的大小:
>>> sys.getsizeof(int())
28
如果这个大小仍然看起来有点大,请记住 Python中的 和(例如)C 中int
的 非常不同。在 Python 中,是一个完全成熟的对象。这意味着有额外的开销。int
`int`
每个 Python 对象除了其他存储外,还至少包含一个引用计数和一个对对象类型的引用;在 64 位机器上,仅这两个东西就占用了 16 个字节!int
内部结构(由标准 CPython 实现决定)也随着时间的推移而发生变化,因此占用的额外存储量取决于您的版本。
int
CPython 3.11 中的对象
整数对象在内部是PyLongObject
代表内存块的 C 类型。定义此类型的代码分布 在多个文件中。以下是相关部分:
typedef struct _longobject PyLongObject;
struct _longobject {
PyObject_VAR_HEAD
digit ob_digit[1];
};
#define PyObject_VAR_HEAD PyVarObject ob_base;
typedef struct {
PyObject ob_base;
Py_ssize_t ob_size; /* Number of items in variable part */
} PyVarObject;
typedef struct _object PyObject;
struct _object {
_PyObject_HEAD_EXTRA
union {
Py_ssize_t ob_refcnt;
#if SIZEOF_VOID_P > 4
PY_UINT32_T ob_refcnt_split[2];
#endif
};
PyTypeObject *ob_type;
};
/* _PyObject_HEAD_EXTRA is nothing on non-debug builds */
# define _PyObject_HEAD_EXTRA
typedef uint32_t digit;
如果我们展开所有的宏并且替换所有的typedef
语句,这就是我们最终得到的结构:
struct PyLongObject {
Py_ssize_t ob_refcnt;
PyTypeObject *ob_type;
Py_ssize_t ob_size; /* Number of items in variable part */
uint32_t ob_digit[1];
};
uint32_t
表示“无符号 32 位整数”,uint32_t ob_digit[1];
表示使用 32 位整数数组来保存整数的(绝对)值。“ 1
”中的ob_digit[1]
“ ”表示数组应初始化为 1 个元素的空间。
因此,我们有以下字节在 Python 中存储整数对象(在 64 位系统上):
8 个字节(64 位,
Py_ssize_t
有符号)用于ob_refcnt
-引用计数8 个字节(64 位,
PyTypeObject*
)用于指向类本身ob_type
的指针int
8 个字节(64 位,
Py_ssize_t
有符号)ob_size
用于存储整数
最后是一个可变长度数组(至少包含 1 个元素),
4 个字节(32 位)用于存储整数的每个部分
此定义附带的注释总结了 Python 3.11 对整数的表示。零不是由大小为 ( ) 零的对象表示的(但实际大小始终至少为 1)。负数由具有负大小属性的对象表示!此注释进一步解释了每个仅使用 30 位来存储值。ob_size
`uint32_t`
>>> sys.getsizeof(0)
28
>>> 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
在 CPython 3.10 及更早版本中,sys.getsizeof(0)
错误地返回 24 而不是 28,这是一个已修复的错误。Python 2 有第二种单独的整数类型,其工作方式略有不同,但总体上相似。
在 32 位系统上您将获得略有不同的结果。