精通 Python 迭代器:工作原理与自定义构建
Python 迭代器
了解 Python 迭代器如何工作,如何用 for 循环或 next() 遍历,以及如何用迭代器协议创建自定义或无限迭代器。
视频:Python 迭代器
Python 中的迭代器
迭代器在 Python 中无处不在。它们支撑 for 循环、列表推导式、生成器和许多内置数据结构,常在幕后工作。
迭代器就是逐个产出数据的对象。在 Python 中,实现 __iter__() 和 __next__() 方法的对象即为迭代器。
能提供迭代器的对象称为可迭代对象。大多数内置容器——列表、元组、字符串、字典——均可迭代。内置 iter() 函数调用对象的 __iter__() 方法获取迭代器。
遍历迭代器
可用 next() 函数手动推进迭代器。迭代器耗尽后引发 StopIteration。
# 定义列表
my_list = [4, 7, 0, 3]
# 用 iter() 获取迭代器
my_iter = iter(my_list)
# 用 next() 遍历
# 输出: 4
print(next(my_iter))
# 输出: 7
print(next(my_iter))
# next(obj) 等同于 obj.__next__()
# 输出: 0
print(my_iter.__next__())
# 输出: 3
print(my_iter.__next__())
# 此处报错,无剩余项
next(my_iter)
输出
4 7 0 3 Traceback (most recent call last): File "<string>", line 24, in <module> next(my_iter) StopIteration
更自然的遍历方式是 for 循环,自动处理迭代器生命周期。
>>> for element in my_list:
... print(element)
... 4 7 0 3
for 循环如何与迭代器配合
for 循环内部转换为:
for element in iterable:
# do something with element
等价于以下逻辑:
# 从可迭代对象创建迭代器对象
iter_obj = iter(iterable)
# 无限循环
while True:
try:
# 获取下一项
element = next(iter_obj)
# 处理 element
except StopIteration:
# 引发 StopIteration 时跳出循环
break
这表明 for 循环本质是依赖迭代器协议和 StopIteration 异常终止的无限循环。
构建自定义迭代器
从零创建迭代器很简单:实现 __iter__() 返回迭代器实例(常为 self),实现 __next__() 产出下一值或耗尽时引发 StopIteration。
下例产出不超过用户指定最大指数的 2 的幂。
class PowTwo:
"""产出 2 的幂的迭代器。"""
def __init__(self, max=0):
self.max = max
def __iter__(self):
self.n = 0
return self
def __next__(self):
if self.n <= self.max:
result = 2 ** self.n
self.n += 1
return result
else:
raise StopIteration
# 创建对象
numbers = PowTwo(3)
# 从对象创建可迭代对象
i = iter(numbers)
# 用 next 获取下一迭代器元素
print(next(i))
print(next(i))
print(next(i))
print(next(i))
print(next(i))
输出
1 2 4 8 Traceback (most recent call last): File "/home/bsoyuj/Desktop/Untitled-1.py", line 32, in <module> print(next(i)) File "<string>", line 18, in __next__ raise StopIteration StopIteration
用 for 循环配合自定义迭代器同样简单:
>>> for i in PowTwo(5):
... print(i)
... 1 2 4 8 16 32
Python 无限迭代器
迭代器可无界。内置 iter() 接受可调用对象和哨兵值:反复调用函数直到返回值等于哨兵。例如:
>>> int()
0
>>> inf = iter(int,1)
>>> next(inf)
0
>>> next(inf)
0
因 int() 总返回 0,iter(int, 1) 永不见哨兵,产生无限迭代器。
也可自建无限迭代器,如产出所有奇数:
class InfIter:
"""返回连续奇数的无限迭代器。"""
def __iter__(self):
self.num = 1
return self
def __next__(self):
num = self.num
self.num += 2
return num
示例运行:
>>> a = iter(InfIter())
>>> next(a)
1
>>> next(a)
3
>>> next(a)
5
>>> next(a)
7
使用无限迭代器时,始终提供终止条件以避免无限循环。
迭代器内存高效,因按需产出项。理论上可生成无限序列——如所有奇数——而不存储整个集合。
创建迭代器的更简单方式,探索 Python 生成器 yield。
Python
- 精通Python数据类型:实战指南
- 精通Python运算符:全面指南
- 精通Python Pass语句:实战指南
- 精通Python函数参数:位置、关键字与默认参数
- 精通 Python 字典:创建、操作与进阶技巧
- Python 闭包详解:嵌套函数如何捕获变量
- 精通 Python datetime:日期、时间与时区实战指南
- 精通 Python time.sleep():最佳实践、多线程与实战案例
- Python 语言概览:高级、可读、交互式与面向对象
- Python 数字类型详解:不可变数值数据的操作与数学函数
- Python 字符串完全指南:创建、访问、格式化与内置方法大全
- Python 元组详解:定义、使用与列表的核心区别