Python中sys.getsizeof内存占用详解与底层原理
本文深入解析Python中sys.getsizeof函数的用法及其底层原理。通过对比C++与Java,揭示Python中一切皆对象的特性导致int、float等类型占用内存远大于传统认知。文章结合代码示例,展示如何查看不同数据类型的实际内存开销,并解释Python解析器将代码映射为C结构体时的额外存储开销,帮助用户更精准地理解Python内存管理机制。
计算机专业背景的开发者常受一种传统观念影响,认为基本数据类型的内存占用是固定的:一个int占用4字节,一个char占用1字节,一个float占用4字节。
在研究Python的getsizeof函数后,发现Python中各基本数据类型(对象)所占用的内存大小与C++或Java等语言存在显著差异。
核心前提在于:Python中一切都是对象。因此,Python中并不存在纯粹的int或float类型,所谓的int实际上是一个Python对象实例。
具体内存占用示例如下:int类型占用28字节,float类型占用24字节,空字符串占用54字节,空列表占用64字节,空字典占用288字节,空集合占用224字节。

此外,使用sys.getsizeof时需注意以下两点限制:
第一,sys.getsizeof仅计算对象实际占用的内存大小,不计算引用本身所消耗的内存。
第二,sys.getsizeof的结果仅作为计算内存大小的参考,并非绝对精确的内存分配值。
这就引出一个问题:为什么Python中各数据类型的占用大小与C++中的定义不一致?
这本质上由Python的实现机制决定。Python代码在运行时由解释器执行,最终被解析为C语言的某种结构。也就是说,Python中的int(或其他类型)在C语言层面映射为一个复杂的结构体。
以Python的int为例,其在C语言中的具体结构如下所示:
typedef struct {
PyObject_HEAD
long ob_ival;
} PyIntObject;
struct _longobject {
long ob_refcnt; // 引用计数
PyTypeObject *ob_type; //变量类型
size_t ob_size; //实际占用内容大小
long ob_digit[1]; //存储的实际python值
};
可以看出,Python实际存储的值只是C结构体中的一个属性。这解释了为何Python的int占用28字节,而C语言中int仅需4字节,因为Python还存储了大量其他相关信息,这些额外信息的体积是实际数值的6倍。
同样地,Python实际的值只是C结构体中的一个属性。这解释了为何Python的int占用28字节,而C语言中int仅需4字节,因为Python还存储了大量其他相关信息,这些额外信息的体积是实际数值的6倍。
补充说明:若需精准控制内存大小,建议使用C++或Java等语言。
补充内容:使用sys.getsizeof查看Python对象的内存占用。
使用sys.getsizeof方法可以查看Python对象的内存占用,单位为字节(byte)。
实际上,该函数内部调用了对象的__sizeof__方法:
In [35]: import sys
In [36]: sys.getsizeof('hello world')
Out[36]: 60
In [37]: 'hello world'.__sizeof__()
Out[37]: 60
部分数据类型在Python 3和Python 2中占用的内存大小有所不同,
例如range对象:
# python3
In [38]: sys.getsizeof(range(999))
Out[38]: 48
In [39]: sys.getsizeof(iter(range(999)))
Out[39]: 48
# python2
>>> sys.getsizeof(range(999))
8064
>>> sys.getsizeof(iter(range(999)))
64
关于这个具体数值的计算方式,仍有待进一步研究。
目前已知:该值包括对象本身的数值、签名(包括数据类型、参数、调用方式等)等一系列数据所占的总内存。可变对象所占内存可能极小,因为对象本质是指针,指向较大的数据区域。
In [65]: s = sys.getsizeof
In [66]: s(1)
Out[66]: 28
In [67]: s(11)
Out[67]: 28
In [68]: s(11111111)
Out[68]: 28
In [69]: s(1111111111)
Out[69]: 32
以上为个人经验总结,希望能给大家一个参考,也希望大家多多支持本站。
本站声明
本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。













