报错是因为类未实现__iter__方法,而for循环依赖该方法获取迭代器;__iter__必须返回含__next__的对象,不能直接返回列表等可迭代但不可迭代器的对象。

为什么直接 for 循环类实例会报 TypeError: 'MyClass' object is not iterable
因为 Python 的 for 语句底层依赖迭代协议:它会先调用对象的 __iter__ 方法获取一个迭代器,再反复调用该迭代器的 __next__ 方法取值,直到抛出 StopIteration。如果类没实现 __iter__,就无法进入这个流程。
__iter__ 必须返回一个带 __next__ 方法的对象,不能直接返回数据
常见错误是让 __iter__ 直接 return self.items(比如列表),这会导致运行时报错——因为列表虽可迭代,但它不是“迭代器”,没有 __next__ 方法;for 会尝试调用 list.__next__,而它不存在。
正确做法是让 __iter__ 返回自身(如果自己实现了 __next__),或返回另一个实现了 __next__ 的对象:
- 返回
self:适用于单次遍历、状态在实例内维护的场景(如计数器、流式读取) - 返回新对象(如
MyIterator(self.data)):适用于支持多次独立遍历,避免状态污染 - 用
yield写生成器函数,Python 自动构造迭代器(最简洁,推荐初学者用)
实现 __next__ 时必须手动管理状态并主动抛出 StopIteration
和生成器不同,手写 __next__ 不会自动终止。漏掉 raise StopIteration 会导致无限循环或索引越界错误(如 IndexError)。
典型结构:
def __next__(self):
if self._index >= len(self._data):
raise StopIteration
item = self._data[self._index]
self._index += 1
return item
-
_index必须是实例变量(如self._index = 0在__init__或__iter__中初始化) - 不能用局部变量,否则每次调用
__next__都重置 - 如果数据源本身可迭代(如列表),也可用内置
iter()+next()委托,但要注意异常传递
多次 for 循环同一个实例时行为不一致?检查是否复用了迭代器
如果类把自身当作迭代器(__iter__ 返回 self),那么第一次 for 结束后,内部索引已走到末尾;第二次 for 会立刻触发 StopIteration,看起来“空了”。这不是 bug,是迭代器的一次性本质。
想支持多次遍历,有三种选择:
-
__iter__每次都返回新实例:return MyClassIterator(self._data) - 在
__iter__中重置状态:self._index = 0; return self(简单但线程不安全) - 改用生成器写法:
def __iter__(self): yield from self._data—— 每次调用都新建生成器,天然可重入
生成器写法最省心,除非你需要精细控制暂停/恢复逻辑或携带额外上下文。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











