2025-10-08 Python 标准库 5——内置类型:迭代器与序列类型
文章目录
- 1. 迭代器类型
- 1.1. 迭代协议核心方法
- 1.1.1. 可迭代对象的 `__iter__()` 方法
- 1.1.2. 迭代器的 `__iter__()` 与 `__next__()` 方法
- 1.2. 迭代器工作流程与代码示例
- 2. 生成器类型
- 3. 序列类型(list, tuple, range)
- 3.1. 通用序列操作
- 3.2. 序列方法
- 3.2.1. `sequence.count(value)`:统计元素出现次数
- 3.2.2. `sequence.index(value, [start[, stop]])`:查找元素首次出现位置
- 3.3. 不可变序列类型
- 3.4. 可变序列类型
- 3.5. 可变序列方法
- 3.6. 列表(list)
- 3.6.1. 列表的创建方式
- 3.6.2. `sort(*, key=None, reverse=False)`
- 3.7. 元组(tuple)
- 3.7.1. 创建方式
- 3.7.2. 不可变性
- 3.8. range 对象
- 3.8.1. 构造方法
- 3.8.2. 属性与操作
- 4. 总结
参考文档:内置类型 — Python 3.13.7 文档
1. 迭代器类型
Python 中的“迭代”是遍历容器(如列表、字典)元素的核心机制,其实现依赖于可迭代对象(Iterable) 和迭代器(Iterator) 两大概念,二者通过特定协议协同工作。序列类型(如 list
、tuple
)默认支持迭代,自定义类也可通过实现协议支持迭代。
1.1. 迭代协议核心方法
迭代机制通过两个关键方法实现,分别对应可迭代对象和迭代器:
1.1.1. 可迭代对象的 __iter__()
方法
容器对象要成为“可迭代对象”,必须定义 __iter__()
方法,该方法需返回一个迭代器对象(而非容器自身)。
- 作用:为容器提供“生成迭代器”的入口,支持不同迭代逻辑(如树的广度优先/深度优先遍历)。
- 对应 Python/C API 中的
tp_iter
槽位。
1.1.2. 迭代器的 __iter__()
与 __next__()
方法
迭代器对象需同时实现以下两个方法,共同构成“迭代器协议”:
__iter__()
:返回迭代器自身(确保迭代器可被for
/in
语句直接使用,与可迭代对象接口统一)。__next__()
:返回迭代器的“下一个元素”,若无剩余元素则必须引发StopIteration
异常(且后续调用需持续引发该异常,否则行为异常)。
- 对应 Python/C API 中的
tp_iter
(__iter__
)和tp_iternext
(__next__
)槽位。
1.2. 迭代器工作流程与代码示例
迭代的核心流程:
- 调用可迭代对象的
__iter__()
生成迭代器; - 反复调用迭代器的
__next__()
获取下一个元素,直到引发StopIteration
; for
循环会自动捕获StopIteration
并终止,无需手动处理异常。
示例:自定义迭代器(遍历 1~n 的整数)
class NumberIterator:"""自定义迭代器:生成 1 到 n 的整数"""def __init__(self, n):self.max = n # 迭代的最大值self.current = 0 # 当前迭代值def __iter__(self):"""返回迭代器自身"""return selfdef __next__(self):"""返回下一个元素,无元素时引发 StopIteration"""self.current += 1if self.current <= self.max:return self.current# 无剩余元素,必须引发 StopIterationraise StopIteration# 1. 创建可迭代对象(此处自定义类既是可迭代对象,也是迭代器)
num_iterable = NumberIterator(5)# 2. 使用 for 循环迭代(自动调用 __iter__ 和 __next__)
print("for 循环迭代结果:")
for num in num_iterable:print(num, end=" ") # 输出:1 2 3 4 5# 3. 手动迭代(模拟 for 循环内部逻辑)
print("\n\n手动迭代结果:")
num_iterable2 = NumberIterator(3)
iterator = iter(num_iterable2) # 调用 __iter__() 获取迭代器
while True:try:num = next(iterator) # 调用 __next__() 获取下一个元素print(num, end=" ") # 输出:1 2 3except StopIteration:break # 捕获异常,终止迭代
2. 生成器类型
生成器(Generator)是 Python 提供的简化迭代器实现的工具——无需手动定义 __iter__()
和 __next__()
方法,只需在函数中使用 yield
表达式,即可自动生成符合迭代器协议的对象(生成器对象)。
- 生成器函数:包含
yield
表达式的函数(调用时不执行函数体,而是返回一个生成器对象); yield
作用:暂停函数执行并返回当前值,下次调用next()
时从暂停处继续执行;- 自动实现协议:生成器对象默认实现
__iter__()
(返回自身)和__next__()
(执行到下一个yield
),无需手动编码。
示例 1:简单生成器(生成斐波那契数列前 n 项)
def fib_generator(n):"""生成器函数:生成斐波那契数列前 n 项"""a, b = 0, 1 # 初始值count = 0while count < n:yield a # 暂停执行,返回当前 a 的值a, b = b, a + b # 下次恢复时从这里继续count += 1# 1. 调用生成器函数,返回生成器对象(不执行函数体)
fib_gen = fib_generator(6)# 2. 使用 for 循环迭代(自动处理 __next__ 和 StopIteration)
print("斐波那契数列前 6 项:")
for num in fib_gen:print(num, end=" ") # 输出:0 1 1 2 3 5# 3. 手动调用 next() 验证
print("\n\n手动调用 next():")
fib_gen2 = fib_generator(3)
print(next(fib_gen2)) # 输出:0(第一次执行到 yield)
print(next(fib_gen2)) # 输出:1(从暂停处继续,执行到下一个 yield)
print(next(fib_gen2)) # 输出:1(再次继续)
# print(next(fib_gen2)) # 报错:StopIteration(无更多 yield)
示例 2:生成器表达式(简化版生成器)
除了生成器函数,还可通过“生成器表达式”快速创建生成器,语法类似列表推导式,但用圆括号包裹(列表推导式用方括号):
# 生成器表达式:生成 1~5 的平方(圆括号包裹)
square_gen = (x ** 2 for x in range(1, 6))print("生成器表达式结果:")
for num in square_gen:print(num, end=" ") # 输出:1 4 9 16 25# 对比:列表推导式(方括号,直接生成列表)
square_list = [x ** 2 for x in range(1, 6)]
print("\n列表推导式结果:", square_list) # 输出:[1, 4, 9, 16, 25]
3. 序列类型(list, tuple, range)
序列是 Python 中最常用的数据结构之一,用于存储有序的元素集合。核心序列类型包括:
- 可变序列:
list
(列表,可修改元素); - 不可变序列:
tuple
(元组,不可修改元素)、range
(范围对象,不可修改且元素为数字)。
此外,str
(字符串)、bytes
(字节串)等也属于序列类型,将在后续章节单独介绍。
3.1. 通用序列操作
所有序列(无论可变/不可变)都支持以下操作,优先级从低到高排列(s
/t
为同类型序列,x
为元素,i
/j
/k
为整数):
运算 | 结果说明 | 关键备注 |
---|---|---|
x in s | 若 s 包含 x 则返回 True ,否则 False | 对 str /bytes 等支持子序列检测(如 "gg" in "eggs" 为 True ) |
x not in s | 与 x in s 逻辑相反 | - |
s + t | 拼接 s 和 t | 不可变序列拼接会生成新对象,效率低;range 不支持拼接 |
s * n / n * s | s 重复 n 次 | n≤0 生成空序列;元素仅引用,不拷贝(易踩坑,见示例) |
s[i] | 获取 s 的第 i 个元素 | i 支持负索引(-1 表示最后一个元素);越界引发 IndexError |
s[i:j] | 切片:s 中从 i 到 j (不包含 j )的元素 | i /j 可省略(默认 0 /len(s) ),支持负索引 |
s[i:j:k] | 步长切片:从 i 到 j ,每 k 个元素取一个 | k 不可为 0 ;k<0 表示反向切片(如 s[::-1] 反转序列) |
len(s) | 返回 s 的长度(元素个数) | - |
min(s) / max(s) | 返回 s 中最小/最大元素 | 要求元素支持比较(如数字、字符串) |
示例 1:in
检测与子序列匹配
# 1. 列表的元素检测
nums = [1, 2, 3, 4]
print("3 in nums:", 3 in nums) # 输出:True
print("5 not in nums:", 5 not in nums) # 输出:True# 2. 字符串的子序列检测(特殊支持)
text = "eggs"
print("'gg' in text:", "gg" in text) # 输出:True(子串匹配)
print("'egg' in text:", "egg" in text) # 输出:True
print("'eggsy' in text:", "eggsy" in text) # 输出:False
示例 2:*
重复的引用陷阱(重点注意)
s * n
会重复序列的引用,而非拷贝元素——若序列元素是可变对象(如列表),修改一个元素会影响所有重复项:
# 错误用法:[[]] * 3 生成的是三个对同一空列表的引用
wrong_lists = [[]] * 3
print("初始 wrong_lists:", wrong_lists) # 输出:[[], [], []]
wrong_lists[0].append(3) # 修改第一个元素(实际修改共享的空列表)
print("修改后 wrong_lists:", wrong_lists) # 输出:[[3], [3], [3]](所有元素都变了)# 正确用法:列表推导式,每次生成新的空列表
correct_lists = [[] for _ in range(3)]
print("\n初始 correct_lists:", correct_lists) # 输出:[[], [], []]
correct_lists[0].append(3)
correct_lists[1].append(5)
print("修改后 correct_lists:", correct_lists) # 输出:[[3], [5], []](仅修改指定元素)
示例 3:切片操作(正/负索引、步长)
s = [0, 1, 2, 3, 4, 5]# 1. 基础切片:s[i:j](默认 i=0,j=len(s))
print("s[2:4]:", s[2:4]) # 输出:[2, 3](索引 2~3,不包含 4)
print("s[:3]:", s[:3]) # 输出:[0, 1, 2](i=0,j=3)
print("s[4:]:", s[4:]) # 输出:[4, 5](i=4,j=len(s)=6)# 2. 负索引切片(-1 表示最后一个元素)
print("s[-3:-1]:", s[-3:-1]) # 输出:[3, 4](等价于 s[3:5])
print("s[:-2]:", s[:-2]) # 输出:[0, 1, 2, 3](等价于 s[0:4])# 3. 步长切片:s[i:j:k]
print("s[::2]:", s[::2]) # 输出:[0, 2, 4](步长 2,全序列)
print("s[1:5:2]:", s[1:5:2]) # 输出:[1, 3](索引 1~4,步长 2)
print("s[::-1]:", s[::-1]) # 输出:[5, 4, 3, 2, 1, 0](步长 -1,反向切片)
3.2. 序列方法
所有序列都支持以下两个基础方法:
3.2.1. sequence.count(value)
:统计元素出现次数
返回 value
在序列中出现的总次数,若 value
不存在则返回 0
。
nums = [1, 2, 2, 3, 2, 4]
print("2 在 nums 中出现次数:", nums.count(2)) # 输出:3
print("5 在 nums 中出现次数:", nums.count(5)) # 输出:0text = "abracadabra"
print("'a' 在 text 中出现次数:", text.count("a")) # 输出:5
3.2.2. sequence.index(value, [start[, stop]])
:查找元素首次出现位置
- 返回
value
在序列中首次出现的索引; - 可选参数
start
/stop
:限定搜索范围(从start
到stop-1
); - 若
value
不存在,引发ValueError
。
nums = [10, 20, 30, 20, 40]
print("20 首次出现的索引:", nums.index(20)) # 输出:1
print("20 在索引 2 之后首次出现的位置:", nums.index(20, 2)) # 输出:3(从索引 2 开始搜索)# 错误:元素不存在
# print(nums.index(50)) # 报错:ValueError: 50 is not in list
3.3. 不可变序列类型
不可变序列(如 tuple
、range
)的核心特性是元素不可修改,且支持 hash()
函数(可作为 dict
的键或 set
的元素)。
关键区别:不可变 vs 可变序列
特性 | 不可变序列(如 tuple) | 可变序列(如 list) |
---|---|---|
元素修改 | 不支持(报错) | 支持 |
hash() 支持 | 支持(元素可哈希时) | 不支持(报错) |
适用场景 | 存储固定数据(如坐标、配置) | 存储动态数据(如待办列表) |
示例:不可变序列的哈希特性
# 1. tuple 可作为 dict 的键(支持 hash)
coord = (10, 20) # 不可变序列 tuple
coord_dict = {coord: "点 A"}
print("coord_dict[(10,20)]:", coord_dict[(10,20)]) # 输出:点 A# 2. list 不可作为 dict 的键(不支持 hash)
coord_list = [10, 20] # 可变序列 list
# coord_dict2 = {coord_list: "点 A"} # 报错:TypeError: unhashable type: 'list'# 3. 不可变序列元素不可修改
t = (1, 2, 3)
# t[0] = 4 # 报错:TypeError: 'tuple' object does not support item assignment
3.4. 可变序列类型
可变序列(如 list
)支持元素修改、删除、扩展等操作,核心操作如下(s
为可变序列,t
为可迭代对象,x
为元素):
运算 | 结果说明 | 关键备注 |
---|---|---|
s[i] = x | 将 s 的第 i 个元素替换为 x | - |
del s[i] | 删除 s 的第 i 个元素 | - |
s[i:j] = t | 将 s 的切片 s[i:j] 替换为 t 的元素 | t 需是可迭代对象,长度可与切片不同(实现插入/删除) |
del s[i:j] | 删除 s 的切片 s[i:j] | 等价于 s[i:j] = [] |
s[i:j:k] = t | 步长切片替换 | t 的长度必须与切片长度一致(否则报错) |
s += t | 扩展 s ,添加 t 的所有元素 | 原地修改(不生成新对象),t 需是可迭代对象 |
s *= n | 重复 s 并原地修改 | n≤0 会清空 s ;元素仅引用,不拷贝(同 s * n 的陷阱) |
示例 1:元素修改与切片替换
s = [0, 1, 2, 3, 4]# 1. 修改单个元素
s[2] = 99
print("修改索引 2 后:", s) # 输出:[0, 1, 99, 3, 4]# 2. 删除单个元素
del s[3]
print("删除索引 3 后:", s) # 输出:[0, 1, 99, 4]# 3. 切片替换(长度不同,实现插入)
s[1:2] = [10, 20, 30] # 将索引 1 的元素(1)替换为 [10,20,30]
print("切片替换后:", s) # 输出:[0, 10, 20, 30, 99, 4]# 4. 步长切片替换(长度必须一致)
s2 = [1, 2, 3, 4, 5, 6]
s2[::2] = [10, 20, 30] # 步长 2 的切片有 3 个元素,t 也需 3 个元素
print("步长切片替换后:", s2) # 输出:[10, 2, 20, 4, 30, 6]# 错误:步长切片替换长度不匹配
# s2[::2] = [10, 20] # 报错:ValueError: attempt to assign sequence of size 2 to extended slice of size 3
示例 2:+=
扩展与 *=
重复
# 1. += 扩展(原地修改,支持任何可迭代对象)
s = [1, 2, 3]
s += (4, 5) # t 是 tuple(可迭代对象)
print("s += (4,5) 后:", s) # 输出:[1, 2, 3, 4, 5]s += "67" # t 是 str(可迭代对象,逐个添加字符)
print("s += '67' 后:", s) # 输出:[1, 2, 3, 4, 5, '6', '7']# 2. *= 重复(原地修改,注意引用陷阱)
s3 = [[1]]
s3 *= 3 # 重复 3 次,共享同一个 [1] 引用
print("初始 s3:", s3) # 输出:[[1], [1], [1]]
s3[0].append(2) # 修改第一个元素(共享引用)
print("修改后 s3:", s3) # 输出:[[1, 2], [1, 2], [1, 2]]
3.5. 可变序列方法
可变序列(如 list
)除通用序列方法外,还支持以下专属方法(均为原地操作,返回 None
):
方法 | 功能说明 | 示例代码(以 list 为例) |
---|---|---|
append(x) | 在序列末尾添加 x (单个元素) | s = [1,2]; s.append(3); print(s) → [1,2,3] |
clear() | 清空序列所有元素(Python 3.3+ 新增) | s = [1,2]; s.clear(); print(s) → [] |
copy() | 返回序列的浅拷贝(Python 3.3+ 新增) | s = [1,2]; s_copy = s.copy(); s[0] = 9; print(s_copy) → [1,2] |
extend(t) | 扩展序列,添加 t 的所有元素(t 需可迭代) | s = [1,2]; s.extend([3,4]); print(s) → [1,2,3,4] |
insert(i, x) | 在索引 i 处插入 x (单个元素) | s = [1,2]; s.insert(1, 9); print(s) → [1,9,2] |
pop([i]) | 删除并返回索引 i 处的元素(默认 -1 ,即最后一个) | s = [1,2,3]; print(s.pop()); print(s) → 3 和 [1,2] |
remove(x) | 删除序列中第一个等于 x 的元素 | s = [1,2,2,3]; s.remove(2); print(s) → [1,2,3] |
reverse() | 原地反转序列元素 | s = [1,2,3]; s.reverse(); print(s) → [3,2,1] |
对比 1:append
(添加单个元素)vs extend
(添加可迭代对象元素)
s = [1, 2, 3]# append:添加整个 list 作为单个元素
s.append([4, 5])
print("append([4,5]) 后:", s) # 输出:[1, 2, 3, [4, 5]](列表嵌套)# extend:添加可迭代对象的每个元素
s2 = [1, 2, 3]
s2.extend([4, 5])
print("extend([4,5]) 后:", s2) # 输出:[1, 2, 3, 4, 5](平展扩展)
对比 2:copy
(浅拷贝)vs 直接赋值(引用传递)
# 直接赋值:两个变量指向同一个列表(引用传递)
s = [1, [2, 3]]
s_assign = s
s[0] = 99 # 修改 s 的元素,s_assign 也会变
s[1].append(4) # 修改嵌套列表,s_assign 同样变
print("s_assign(直接赋值):", s_assign) # 输出:[99, [2, 3, 4]]# copy:浅拷贝(顶层元素独立,嵌套元素仍共享引用)
s3 = [1, [2, 3]]
s_copy = s3.copy()
s3[0] = 99 # 修改顶层元素,s_copy 不变
s3[1].append(4) # 修改嵌套列表,s_copy 会变(共享引用)
print("s_copy(浅拷贝):", s_copy) # 输出:[1, [2, 3, 4]]
3.6. 列表(list)
列表是 Python 中最常用的可变序列,适用于存储动态变化的元素集合(如用户列表、日志记录)。
3.6.1. 列表的创建方式
列表有 4 种常见创建方式:
- 空列表:
[]
; - 直接初始化:
[a, b, c]
(元素用逗号分隔); - 列表推导式:
[x for x in iterable]
(简洁生成列表); - 构造器
list(iterable)
:将可迭代对象转换为列表(如list("abc")
→['a','b','c']
)。
示例:列表的创建
# 1. 空列表
empty_list = []
print("空列表:", empty_list) # 输出:[]# 2. 直接初始化
fruits = ["apple", "banana", "orange"]
print("直接初始化:", fruits) # 输出:['apple', 'banana', 'orange']# 3. 列表推导式:生成 1~5 的平方
square_list = [x ** 2 for x in range(1, 6)]
print("列表推导式:", square_list) # 输出:[1, 4, 9, 16, 25]# 4. 构造器 list(iterable)
str_to_list = list("hello") # 字符串转列表
tuple_to_list = list((1, 2, 3)) # 元组转列表
print("字符串转列表:", str_to_list) # 输出:['h', 'e', 'l', 'l', 'o']
print("元组转列表:", tuple_to_list) # 输出:[1, 2, 3]
3.6.2. sort(*, key=None, reverse=False)
list
除了可变序列的通用方法外,还额外提供 sort()
方法,用于原地排序(不生成新列表,返回 None
)。
key
:指定排序键函数(接收一个元素,返回用于比较的键),默认None
(直接比较元素);reverse
:布尔值,True
表示降序排序,默认False
(升序);- 稳定性:排序是稳定的(比较相等的元素保持原顺序)。
示例:sort()
方法的使用
# 示例 1:基础排序(升序/降序)
nums = [3, 1, 4, 1, 5]
nums.sort() # 默认升序
print("升序排序:", nums) # 输出:[1, 1, 3, 4, 5]nums.sort(reverse=True) # 降序
print("降序排序:", nums) # 输出:[5, 4, 3, 1, 1]# 示例 2:按 key 排序(按字符串长度)
words = ["apple", "banana", "cherry", "date"]
words.sort(key=len) # 按字符串长度升序
print("按长度排序:", words) # 输出:['date', 'apple', 'banana', 'cherry']# 示例 3:稳定排序(多重排序)
# 先按年龄升序,同年龄按姓名升序(稳定排序保证姓名顺序)
people = [("Alice", 25), ("Bob", 20), ("Charlie", 25), ("David", 20)]
people.sort(key=lambda x: x[1]) # 第一步:按年龄升序
people.sort(key=lambda x: x[0]) # 第二步:按姓名升序(同年龄保持年龄排序后的顺序)
print("多重排序:", people) # 输出:[('Alice', 25), ('Bob', 20), ('Charlie', 25), ('David', 20)]
注意:sort()
vs sorted()
list.sort()
:原地排序,返回None
(仅列表可用);sorted(iterable)
:生成新的排序后的列表,不修改原对象(支持所有可迭代对象)。
nums = [3, 1, 4]
new_nums = sorted(nums) # 生成新列表
print("原列表:", nums) # 输出:[3, 1, 4](未修改)
print("新列表:", new_nums) # 输出:[1, 3, 4](已排序)
3.7. 元组(tuple)
元组是不可变序列,适用于存储固定不变的数据(如坐标、函数返回的多值结果),其核心特点是“不可修改”和“支持哈希”。
3.7.1. 创建方式
元组的创建依赖逗号(圆括号仅为避免歧义,非必需),常见方式:
- 空元组:
()
; - 单元组:
(a,)
或a,
(必须加逗号,否则是普通变量); - 多元素元组:
(a, b, c)
或a, b, c
; - 构造器
tuple(iterable)
:将可迭代对象转换为元组。
示例:元组的创建(重点注意单元组)
# 1. 空元组
empty_tuple = ()
print("空元组:", empty_tuple, type(empty_tuple)) # 输出:() <class 'tuple'># 2. 单元组(必须加逗号,否则是 int 类型)
single_tuple1 = (5,) # 正确:元组
single_tuple2 = 5, # 正确:元组
wrong_single = (5) # 错误:int 类型
print("单元组 1:", single_tuple1, type(single_tuple1)) # 输出:(5,) <class 'tuple'>
print("单元组 2:", single_tuple2, type(single_tuple2)) # 输出:(5,) <class 'tuple'>
print("错误单元组:", wrong_single, type(wrong_single)) # 输出:5 <class 'int'># 3. 多元素元组(圆括号可选)
t1 = (1, 2, 3)
t2 = 4, 5, 6
print("多元素元组 1:", t1) # 输出:(1, 2, 3)
print("多元素元组 2:", t2) # 输出:(4, 5, 6)# 4. 构造器 tuple(iterable)
list_to_tuple = tuple([1, 2, 3])
str_to_tuple = tuple("hello")
print("列表转元组:", list_to_tuple) # 输出:(1, 2, 3)
print("字符串转元组:", str_to_tuple) # 输出:('h', 'e', 'l', 'l', 'o')
3.7.2. 不可变性
元组的元素一旦创建无法修改(包括添加、删除、替换),但若元素是可变对象(如 list),则可变对象内部可修改(元组仅存储对象引用)。
示例:元组的不可变性与嵌套修改
t = (1, [2, 3], 4)# 错误:修改元组的元素(不可变)
# t[0] = 99 # 报错:TypeError: 'tuple' object does not support item assignment# 正确:修改元组中的可变元素(list 内部)
t[1].append(5)
print("修改嵌套列表后:", t) # 输出:(1, [2, 3, 5], 4)(元组引用不变,列表内部变化)
3.8. range 对象
range
类型表示不可变的整数序列,主要用于 for
循环中指定循环次数,其核心优势是节省内存(仅存储 start
、stop
、step
,不存储所有元素)。
3.8.1. 构造方法
range
有 3 种构造形式(参数均为整数,step
不可为 0):
range(stop)
:从0
开始,到stop-1
结束,步长1
;range(start, stop)
:从start
开始,到stop-1
结束,步长1
;range(start, stop, step)
:从start
开始,到stop
结束(不包含stop
),步长step
(step>0
升序,step<0
降序)。
示例:range 对象的创建与转换
# 1. range(stop):0 ~ stop-1
r1 = range(5)
print("range(5) 转列表:", list(r1)) # 输出:[0, 1, 2, 3, 4]# 2. range(start, stop):start ~ stop-1
r2 = range(1, 6)
print("range(1,6) 转列表:", list(r2)) # 输出:[1, 2, 3, 4, 5]# 3. range(start, stop, step):步长控制
r3 = range(0, 10, 2) # 步长 2,升序
r4 = range(10, 0, -2) # 步长 -2,降序
print("range(0,10,2) 转列表:", list(r3)) # 输出:[0, 2, 4, 6, 8]
print("range(10,0,-2) 转列表:", list(r4)) # 输出:[10, 8, 6, 4, 2]# 4. 空 range(不符合范围条件)
r5 = range(5, 1) # start > stop,步长默认 1(正)
print("range(5,1) 转列表:", list(r5)) # 输出:[]
3.8.2. 属性与操作
range
对象支持以下特性(Python 3.2+ 实现 Sequence
ABC,3.3+ 新增属性):
- 属性:
start
(起始值)、stop
(终止值)、step
(步长); - 操作:
in
/not in
(成员检测)、index()
(元素索引)、切片
(返回新range
对象); - 相等比较:两个
range
对象若表示相同序列,则相等(无论start
/stop
/step
是否相同,如range(0) == range(2,1,3)
)。
示例:range 的属性与操作
r = range(0, 20, 2)# 1. 访问属性
print("r.start:", r.start) # 输出:0
print("r.stop:", r.stop) # 输出:20
print("r.step:", r.step) # 输出:2# 2. 成员检测(固定时间,无需遍历)
print("10 in r:", 10 in r) # 输出:True
print("11 in r:", 11 in r) # 输出:False# 3. 元素索引
print("r.index(10):", r.index(10)) # 输出:5(10 是第 5 个元素,索引从 0 开始)# 4. 切片(返回新的 range 对象)
r_slice = r[2:6] # 从索引 2 到 5,步长不变
print("r[2:6] 转列表:", list(r_slice)) # 输出:[4, 6, 8, 10]# 5. 相等比较(序列相同则相等)
r6 = range(0, 4, 2)
r7 = range(0, 3, 2)
print("r6 == r7:", r6 == r7) # 输出:True(均表示 [0,2])
print("r6.start == r7.start:", r6.start == r7.start) # 输出:True(但 stop 不同)
4. 总结
- 迭代器:通过
__iter__()
和__next__()
实现迭代,需手动处理StopIteration
; - 生成器:用
yield
简化迭代器实现,支持生成器函数和表达式,代码更简洁; - 序列类型:
- 通用操作:
in
/+
/*
/切片/count
/index
,适用于所有序列; - 不可变序列(
tuple
/range
):元素不可修改,支持hash
,适用于固定数据; - 可变序列(
list
):元素可修改,支持append
/extend
/sort
等方法,适用于动态数据;
- 通用操作:
- 性能提示:
range
节省内存,list.sort()
原地排序,s * n
需注意引用陷阱。