Python 2 中 range 立即创建列表,xrange 是惰性迭代器;Python 3 的 range 是不可变序列类型,支持切片、len、in 等操作且内存恒定。

Python 2 中 range 立即分配内存,xrange 是惰性迭代器
Python 2 的 range(10**7) 会直接创建含一千万个整数的 list 对象,触发 MemoryError 很常见;而 xrange(10**7) 只存三个参数(start、stop、step),每次循环调用 next() 才算一个值,内存占用恒定在几百字节。实测 1000 万次循环,xrange 启动快、GC 压力小,耗时通常低 30%–50%。
常见错误现象:
- 在 Python 2 脚本里对大范围用
range,本地跑通但上线 OOM - 误以为
xrange(100)支持xrange(100)[5:10]—— 实际报TypeError: sequence index must be integer, not 'slice'
Python 3 的 range 不是生成器,而是不可变序列类型
Python 3 彻底移除了 xrange,现在的 range 是一个自定义类对象,行为上更接近“智能切片容器”,不是传统意义上的生成器或迭代器。它支持 len()、__contains__(比如 999 in range(1000) 是 O(1))、正负索引、切片(返回新 range 对象),且内存占用与范围大小无关(约 48 字节)。
关键区别点:
立即学习“Python免费学习笔记(深入)”;
-
range(10**8)在 Python 3 中不会爆内存,但list(range(10**8))会立刻分配 800MB+ 内存 -
range(5)[::-1]在 Python 2 返回[4, 3, 2, 1, 0](list),Python 3 返回range(4, -1, -1)(仍是 range) - Python 3.2+ 的
range支持pickle,但 3.0–3.1 不行 —— 跨版本序列化时容易静默失败
跨版本迁移时最易踩的兼容性坑
把 Python 2 代码里的 xrange 全替成 range 看似能跑,但某些边界行为会出问题:
- 类型检查:Python 2 中
isinstance(xrange(10), collections.Iterator)为True,Python 3 中isinstance(range(10), collections.Iterator)是False(它是Sequence) - 相等性判断:
xrange(0, 10, 1) == xrange(0, 10)在 Python 2 恒为False(默认对象比较),Python 3 中range(0, 10, 1) == range(0, 10)是True - 数值溢出:
range(2**63)在 Python 3 会抛OverflowError,Python 2 的range可能静默截断或崩溃
什么时候真该关心“快”和“省内存”?
绝大多数场景根本不用纠结 —— for i in range(100) 或 range(1000) 在两个版本下差异都在纳秒级,远低于解释器开销和循环体本身的成本。真正要动手优化的只有两种情况:
- 外层嵌套循环中用超大范围(如
for i in range(10**6): for j in range(10**6): ...),此时 Python 2 必须用xrange,Python 3 用原生range即可 - 需要做存在性判断(如
if n in range(low, high)),Python 3 的range是 O(1),而 Python 2 的range是 O(n),xrange则不支持in操作
别被“生成器”这个词带偏:Python 3 的 range 既不是生成器也不是迭代器,它是个带数学语义的轻量序列——这个本质,决定了它在哪种操作下快、在哪种操作下不能用。



















