python 2 中 xrange 比 range 更快更省内存,因 xrange 返回惰性对象,只存参数不生成元素;python 3 的 range 行为与之相同,已移除 xrange。

Python 2 中 xrange 比 range 快且省内存
在 Python 2 中,range 返回的是一个完整列表,比如 range(1000000) 会立刻分配百万个整数对象的内存;而 xrange 返回的是一个惰性生成的 xrange 对象,只存起点、终点和步长,遍历时按需计算,不占额外内存。
常见错误现象:用 range(10**7) 在 Python 2 中直接触发 MemoryError,但换成 xrange(10**7) 就能正常循环。
- 适用场景:大范围 for 循环、嵌套循环的外层计数、需要迭代但不需随机索引时
- 注意:
xrange不支持切片、list方法或直接打印全部内容(print 会显示对象地址) - 性能差异明显:1000 万次循环,
xrange启动快、GC 压力小,实测耗时通常低 30%–50%
Python 3 中只有 range,它本质就是 Python 2 的 xrange
Python 3 彻底移除了 xrange,现在的 range 是一个不可变序列类型,行为和内存模型都与 Python 2 的 xrange 一致——它不预生成元素,只存储参数,支持 len()、__contains__(如 5 in range(10)),也支持切片(返回新 range 对象)。
常见错误现象:Python 3 代码里写 xrange(10) 直接报 NameError: name 'xrange' is not defined;或者误以为 range(10**8) 会爆内存,其实不会。
快速生成专业的 Python 脚本和应用代码。一键创建完整项目结构,支持CLI、API、爬虫、Bot、Django等多种项目类型,包含完整的项目结构、配置文件、依赖管理、测试、README和文档。
-
range对象本身内存占用恒定(约 48 字节),与起止值大小无关 - 但调用
list(range(n))会强制展开,此时才分配 O(n) 内存 - 兼容性提醒:从 Python 2 迁移到 3 时,所有
xrange可直接替换为range,无需逻辑改动
不同版本下 range 的底层实现差异影响边界行为
Python 2 的 range 是纯列表,所以支持任意列表操作;Python 3 的 range 是自定义类型,虽然接口兼容,但某些边缘行为不一致——这容易在跨版本移植或类型检查时踩坑。
- Python 2:
range(5)[::-1]返回[4, 3, 2, 1, 0](列表切片) - Python 3:
range(5)[::-1]返回range(4, -1, -1)(仍是 range 对象) -
range在 Python 3.2+ 支持__reduce__,可被 pickle;但早期 3.0–3.1 版本中不能直接序列化 - 数值过大时(如
range(2**63)),Python 3 会做溢出检查并抛OverflowError,而 Python 2 的range可能静默截断或崩溃
什么时候真该关心“快”和“内存”?
绝大多数日常循环(比如 for i in range(100))根本不用纠结——两者的差异在纳秒级,编译器优化和解释器开销远大于它们本身的差别。真正需要较真的场景很具体:
- 循环上千万次且在内存受限环境(如嵌入式、容器限 64MB)运行
- 构建超大索引集但只用部分值(例如
range(0, 10**9, 1000)),这时range的 O(1) 空间优势才体现出来 - 做性能敏感的数值计算,误把
list(range(...))当成轻量结构传参,结果拖慢整个 pipeline
最容易被忽略的一点:很多人以为 range “快”是因为它用 C 实现——其实关键不在实现语言,而在它根本不生成数据。只要没调用 list()、tuple() 或索引越界访问(触发全量计算),它就始终是那个几十字节的壳。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










