Python range()与numpy.arange()的区别及空间占用差异疑问
为什么你的测试结果和认知不符?
这个问题其实是因为你误解了sys.getsizeof()的作用,以及range和numpy.arange()的本质差异——咱们一步步拆解:
1. range 是惰性序列,根本不存储元素
Python的range()返回的是一个惰性迭代器对象(Python 3版本),它不会预先把所有元素都存在内存里,只存储三个核心参数:start、stop、step,再加上一些内部管理属性。所以sys.getsizeof(range(1,10000))返回的48字节,只是这个小对象本身的大小——不管你range的范围多大,这个对象的大小基本是固定的。
你可以试试sys.getsizeof(range(1, 1000000)),结果还是差不多的数值,因为它从来没存储过那上百万个元素。
2. numpy.arange() 返回的是实际存储元素的数组
numpy.arange()返回的是一个numpy.ndarray对象,这个对象本身需要存储元数据(比如dtype、shape、strides等),同时会把所有元素实际存在内存里。
看你的例子:
np.arange(1,10000, dtype=np.int8)生成了9999个元素(从1到9999)- 每个
int8类型的元素占用1字节,所以元素总大小是9999字节 - 再加上
ndarray对象本身的元数据(大概96字节左右),9999+96=10095,正好和你看到的输出一致。
3. 什么时候numpy.arange()才会更省空间?
当你需要把序列的所有元素都存在内存里的时候,numpy的优势就体现出来了。比如对比:
import sys import numpy as np # 把range转成list,实际存储所有元素 x_list = list(range(1,10000)) print(sys.getsizeof(x_list)) # 大概是80096字节(不同版本可能略有差异) # 再算每个int元素的大小:每个Python int对象在64位系统占~28字节,9999个就是≈279972字节,加上list本身的开销,总内存远大于numpy数组 # numpy数组的大小 a = np.arange(1,10000, dtype=np.int8) print(sys.getsizeof(a)) # 10095字节
这时候你就能看到,numpy数组存储相同数量的元素,内存占用只有list的1/8左右(如果用int32,也比Python int省很多)。
总结两者的核心差异
range:惰性迭代,不存储元素,适合只需要迭代遍历的场景,内存开销极小(固定大小),但不支持数值计算。numpy.arange:生成实际存储的数组,支持高效数值计算,当需要存储大量数值时,内存效率远高于Python的list/int组合,但本身对象包含元素存储,所以sys.getsizeof()会显示更大的数值。
内容的提问来源于stack exchange,提问作者AshishSingh007




