Python 迭代器协议要求迭代器只能单向遍历且不可重置;若需多次遍历,应分离「可迭代对象」与「迭代器」职责,让 __iter__ 每次返回全新迭代器实例。
python 迭代器协议要求迭代器只能单向遍历且不可重置;若需多次遍历,应分离「可迭代对象」与「迭代器」职责,让 `__iter__` 每次返回全新迭代器实例。
在 Python 中,迭代器(iterator)和可迭代对象(iterable)是两个明确区分的概念——这是理解问题本质的关键。内置类型如 list、tuple、str 等属于 可迭代对象,它们自身不保存迭代状态,而是每次调用 __iter__() 时新建一个独立的迭代器实例,因此可被无限次遍历。
而你当前的 MyIterator 类混淆了二者角色:它既是可迭代对象(实现了 __iter__),又是迭代器(实现了 __next__),且内部状态(_iteration_index)在首次遍历后已耗尽。一旦 __next__() 抛出 StopIteration,根据 Python 官方规范,该迭代器即进入“已终止”状态,后续调用必须持续抛出 StopIteration,绝不允许重置索引重新开始。强行重置会破坏迭代器协议,导致 for 循环等语言结构行为异常。
✅ 正确做法是遵循标准设计模式:将逻辑拆分为两个类
- MyIterable:可迭代对象,不保存状态,__iter__() 每次返回一个新 MyIterator 实例
- MyIterator:真正的迭代器,仅负责单次遍历,持有独立索引
以下是推荐实现(已修复原答案中的小错误,如 self.my_list = list → self.my_list = my_list):
立即学习“Python免费学习笔记(深入)”;
class MyIterable:
def __init__(self, my_list: list):
self.my_list = my_list # 修正:原答案误写为 list
def __iter__(self):
return MyIterator(self.my_list)
class MyIterator:
def __init__(self, data: list):
self.data = data
self.index = 0
def __iter__(self):
return self
def __next__(self):
if self.index >= len(self.data):
raise StopIteration
value = self.data[self.index]
self.index += 1
return value
# ✅ 使用示例:可无限次遍历
obj = MyIterable([10, 20, 30])
for x in obj:
print(x) # 输出: 10, 20, 30
for y in obj:
print(y) # 再次输出: 10, 20, 30 —— 成功!? 更简洁的替代方案:使用生成器函数
若无需复杂状态管理,直接在 __iter__ 中用 yield from 返回生成器,Python 会自动为你创建新迭代器:
class MyIterable:
def __init__(self, my_list: list):
self.my_list = my_list
def __iter__(self):
yield from self.my_list # 每次调用都生成全新迭代器
# 效果完全一致,代码更少,不易出错⚠️ 注意事项:
- 切勿在迭代过程中修改底层数据结构(如 list.append()),这会导致 IndexError 或跳过/重复元素;
- 若需支持 len() 或下标访问,应在 MyIterable 中实现 __len__ 和 __getitem__;
- MyIterator 的 __iter__() 必须返回 self(满足迭代器协议),但 MyIterable 的 __iter__() 必须返回新对象;
- 调试时可用 iter(obj) 显式获取迭代器,验证是否每次返回不同实例:id(iter(obj)) != id(iter(obj)) 应为 True。
总结:可重复迭代的本质,不在于“重置”,而在于“按需新建”。坚守可迭代对象与迭代器的职责分离,是写出符合 Python 惯例、健壮且可维护的自定义迭代逻辑的基石。


















