python 3的range对象内存占用恒定,仅存储start、stop、step等元信息,不存实际数字;支持o(1)数学式成员判断,而py2的xrange不支持切片和__contains__。

Python 3 的 range 对象内存占用恒定,和范围大小无关
它不存数字,只存 start、stop、step 三个整数和一些元信息。无论 range(10) 还是 range(10**15),对象本身都只占约 48 字节。你可以用 sys.getsizeof(range(10**6)) 和 sys.getsizeof(range(10**15)) 实测验证——结果几乎一样。
而 Python 2 的 xrange 虽然也是惰性,但它的实现更轻量、也更受限:不支持切片返回新 range、不支持 __contains__(比如 999 in xrange(1000) 在 Py2 中是线性扫描,Py3 是 O(1) 数学判断)。
range 支持数学式成员判断,不是遍历出来的
Python 3 的 range 把“是否在范围内”变成一个算术问题:给定 n,只要满足 (n - start) % step == 0 且 start ≤ n (正步长时),就立刻返回 <code>True。这不需要生成任何中间值,也不触发迭代。
对比 Python 2 的 xrange:999 in xrange(1000) 实际上会从头开始一个个比对,最坏情况要执行 1000 次判断。这不是内存问题,而是算法层面的差异——Py3 的 range 是真正意义上的“序列抽象”,Py2 的 xrange 更接近“单次遍历生成器”。
-
999 in range(1000)→ 瞬间返回True -
10**12 in range(10**12 + 1)→ 仍是 O(1),不卡顿 -
10**12 in xrange(10**12 + 1)(Py2)→ 不建议,实际会尝试生成到那一项,极慢甚至失败
切片返回新 range,不是列表也不是拷贝
Python 3 的 range[::] 不展开数据,而是用原参数推导出新 start/stop/step,构造另一个恒定内存的 range 对象。比如:
r = range(0, 100, 2) # 0, 2, 4, ..., 98 s = r[5:15:2] # 等价于 range(10, 30, 4) → 10, 14, 18, 22, 26
这个 s 和 r 一样,只占几十字节。而 Python 2 的 xrange 根本不支持切片操作,写 xrange(10)[2:5] 直接抛 TypeError。
别误调 list(range(n)) —— 真正爆内存的是这一句
range 本身再大也不吃内存,但一旦你显式转成列表,就立刻分配 O(n) 空间。比如 list(range(10**8)) 在多数机器上会直接触发 MemoryError。
常见踩坑场景:
- 调试时写
print(range(10**6))→ Py3 会显示range(0, 1000000),安全;但若写成print(list(range(10**6))),就真把百万整数全加载进内存了 - 想“预计算索引”而写
indices = list(range(len(data)))→ 完全没必要,直接用enumerate(data)或range(len(data))迭代即可 - 兼容 Py2/Py3 的旧代码里保留了
list(xrange(...)),迁移到 Py3 后没删list(),导致性能倒退
真正需要全部数字时再展开;绝大多数循环、索引、判断场景,直接用 range 就够了——它省的不是“一点内存”,而是把 O(n) 变成 O(1) 的底层契约。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











