飞翔飞翔
主页
  • 计算机基础

    • TCP/IP协议
    • Linux命令
  • 数据库

    • SQL教程
  • 编程语言

    • C语言
    • Python2
    • Python3
  • 数据格式

    • JSON教程
  • 工具

    • Markdown指南
  • Git

    • GitFlow
  • Quartz

    • Quartz教程
  • Java

    • Java设计模式
  • 缓存

    • Redis教程
联系
阿里云
主页
  • 计算机基础

    • TCP/IP协议
    • Linux命令
  • 数据库

    • SQL教程
  • 编程语言

    • C语言
    • Python2
    • Python3
  • 数据格式

    • JSON教程
  • 工具

    • Markdown指南
  • Git

    • GitFlow
  • Quartz

    • Quartz教程
  • Java

    • Java设计模式
  • 缓存

    • Redis教程
联系
阿里云
  • 学习路径
  • 第1章 Python简介

    • Python是什么
    • 安装与运行
    • 交互式解释器
    • 注释与编码规范
  • 第2章 变量与数据类型

    • 变量与对象
    • 整数 int
    • 浮点数 float
    • 复数 complex
    • 布尔值 bool
    • 字符串 str
    • 空值 None
    • 类型转换
  • 第3章 运算符与表达式

    • 算术运算符
    • 比较运算符
    • 赋值运算符
    • 逻辑运算符
    • 位运算符
    • 身份与成员运算符
    • 海象运算符
    • 运算符优先级
  • 第4章 流程控制

    • if 语句
    • if-else 语句
    • if-elif-else 语句
    • match-case 语句
    • 条件表达式(三元运算符)
    • while 循环
    • for 循环
    • range 函数
    • break 与 continue
    • 循环的 else 子句
    • pass 语句
  • 第5章 数据结构

    • 列表创建与索引
    • 列表方法
    • 列表推导式
    • 元组
    • 序列解包
    • 集合
    • 字典创建与访问
    • 字典方法
    • 字典推导式
    • range 对象
  • 第6章 函数

    • 定义函数
    • 位置参数与关键字参数
    • 默认参数
    • 可变参数
    • 解包实参
    • 函数返回值
    • lambda 表达式
    • 文档字符串与注解
    • 作用域与命名空间
    • global 与 nonlocal
  • 第7章 模块与包

    • 模块导入
    • 模块搜索路径
    • 包与相对导入
    • 标准库概览
  • 第8章 文件与输入输出

    • 文件读写
    • 上下文管理器
    • 字符串格式化
    • JSON 与 CSV
  • 第9章 面向对象

    • 类与对象
    • 方法
    • 实例变量与类变量
    • 私有变量
    • 继承
    • 多重继承
    • 魔术方法
    • 属性装饰器
    • 数据类 dataclass
  • 第10章 异常处理

    • 语法错误与异常
    • try-except
    • 异常链与 raise
    • 清理操作
    • 自定义异常
  • 第11章 迭代器与生成器

    • 迭代器协议
    • 生成器
    • 生成器表达式
    • 迭代工具
  • 第12章 高级特性

    • 装饰器
    • 函数式编程
  • 第13章 工程实践

    • 测试与调试
    • 代码质量
    • 虚拟环境

range 对象

range 是 Python 内置的不可变序列类型,用于生成等差整数序列。它并非真正存储所有数字的列表,而是一个"按需计算"的惰性对象,因此在表示巨大数字范围时具有极高的内存效率。

range 的类型与构造

range 有三种构造形式:

range(5)          # 0, 1, 2, 3, 4,默认从0开始,步长1
range(1, 6)       # 1, 2, 3, 4, 5,指定起始和结束(结束不包含)
range(0, 10, 2)   # 0, 2, 4, 6, 8,指定步长

参数规则与切片一致:start 包含,stop 不包含,步长默认为 1。步长可以是负数,实现递减序列:

list(range(5, 0, -1))    # [5, 4, 3, 2, 1]
list(range(10, -1, -2))  # [10, 8, 6, 4, 2, 0]

当步长为正时,start 必须小于 stop,否则结果为空;步长为负时,start 必须大于 stop:

list(range(5, 1))        # [],start > stop 且步长为正
list(range(1, 5, -1))    # [],start < stop 且步长为负

步长不能为 0,否则会抛出 ValueError:

range(1, 5, 0)   # ValueError: range() arg 3 must not be zero

惰性求值与不可变性

range 对象在创建时不生成任何数字,只记录 start、stop、step 三个参数。当你迭代它或请求特定索引时,才实时计算出对应的值:

r = range(1000000)
print(r)         # range(0, 1000000),不占用大量内存
print(len(r))    # 1000000,长度可立即确定
print(r[999999]) # 999999,按需计算

这种惰性机制使 range 的内存占用与范围大小无关。一个 range(0, 10**9) 对象仅占几十字节,而等价的列表需要约 8GB 内存。

range 是不可变序列,支持索引访问和切片,但不支持元素赋值:

r = range(10)
r[3]             # 3,支持索引
r[2:5]           # range(2, 5),支持切片,返回新的 range 对象
r[3] = 99        # TypeError: 'range' object does not support item assignment

切片操作返回新的 range 对象,而非列表。若需查看具体值,必须显式转换:

r = range(0, 20, 2)
r[3:6]           # range(6, 12, 2)
list(r[3:6])     # [6, 8, 10]

与列表的转换

range 本身不是列表,但可以通过 list() 轻松转换:

list(range(5))           # [0, 1, 2, 3, 4]
list(range(3, 8))        # [3, 4, 5, 6, 7]
list(range(0, 10, 3))    # [0, 3, 6, 9]

在需要多次随机访问或修改元素的场景下,转换为列表是必要的;但在仅需顺序迭代的循环中,直接使用 range 即可,无需转换:

# 不需要 list(),直接迭代更省内存
for i in range(1000000):
    pass

# 错误示范:浪费内存
for i in list(range(1000000)):
    pass

range 支持 in 成员检测,但实现方式与列表不同。对于 range,成员检测是 O(1) 的算术判断;对于列表,则是 O(n) 的线性扫描:

r = range(0, 1000000, 2)
999998 in r      # True,瞬间完成
999999 in r      # False,瞬间完成

判断逻辑是:检查数值是否在 [start, stop) 区间内,且与 start 的差能被 step 整除。

内存效率对比

通过 sys.getsizeof() 可以直观感受 range 的内存优势:

import sys

r = range(1000000)
lst = list(r)

print(sys.getsizeof(r))      # 约 48 字节
print(sys.getsizeof(lst))    # 约 8000048 字节(800多万字节)

range 的内存占用恒定为几十字节,而列表需要为每个元素分配指针和对象开销。在表示大规模整数序列时,range 是无可替代的选择。

等效性判断

两个 range 对象即使参数不同,只要生成的序列完全相同,就被视为相等:

range(0, 5) == range(5)           # True
range(0, 6, 2) == range(0, 5, 2)  # True,都生成 [0, 2, 4]

但它们的参数元组 (start, stop, step) 可能不同,因此 repr 输出也不同。这种"值相等但构造不同"的特性,是 range 作为数学抽象而非物理存储的体现。

上一页
字典推导式