__iter__() 必须返回迭代器对象(含__next__()),若返回自身却未实现__next__(),则next()调用时报TypeError;其职责是提供新迭代器,而非自变迭代器。

为什么 __iter__() 返回的不是自己,next() 就会报错
因为 Python 的 for 循环和内置函数(如 list()、sum())只认「迭代器协议」:对象必须有 __iter__() 方法,且该方法返回一个带 __next__() 方法的对象。如果 __iter__() 直接返回 self,那它自己就得实现 __next__();如果没实现,调用 next() 时就会抛 TypeError: 'X' object is not an iterator。
常见错误现象:for item in my_obj: 报错说对象不可迭代,或 next(iter(my_obj)) 崩在 next() 上。
-
__iter__()的职责是「提供一个迭代器」,不是「让自己变成迭代器」 -
可迭代对象(如
list、自定义类)≠ 迭代器;迭代器是「一次性的、有状态的」 - 想复用,得每次调用
__iter__()都返回新迭代器实例,否则第二次for会空跑
next() 的第二个参数到底用来干啥
它是「哨兵值」,用于避免 StopIteration 异常。当迭代器耗尽时,不抛异常,而是直接返回这个默认值。
使用场景:读文件行、解析流式数据、做「尝试取一个」的逻辑,比如从配置里找第一个非空值。
- 写成
next(iterator, None)是安全兜底,但要注意:返回None可能和真实数据冲突 - 别滥用——如果业务逻辑依赖「是否结束」,用
try/except StopIteration更清晰 - 性能无差异,但语义更明确:你主动选择了「静默终止」而非「异常控制流」
示例:next(iter([1, 2]), 'empty') → 1;next(iter([]), 'empty') → 'empty'
让 macOS 自动化像说话一样简单 —— 用代码控制你的 Mac,无需学习 AppleScript 系统要求 macOS 14+ (Sonoma) Python 3.9+ 需要开启:辅助功能 + 屏幕录制权限
自定义类怎么同时支持 for 和 next()
关键在两层分离:类本身是可迭代对象,内部另写一个迭代器类(或用生成器),由 __iter__() 返回它。
容易踩的坑:把状态存在可迭代对象上,导致多次遍历相互干扰;或者忘记在迭代器里维护 self._index 这类状态变量。
- 迭代器必须实现
__next__(),且内部要有状态(如索引、游标、缓存) -
__iter__()每次都应返回新迭代器实例,例如return MyIterator(self.data) - 如果用生成器函数实现
__iter__()(yield),它天然满足迭代器协议,但无法共享状态,适合只读、无副作用场景
示例片段:
def __iter__(self): yield from ...
- 生成器函数返回的是
generator对象,它既是可迭代对象也是迭代器(iter(gen) is gen成立) - 手写类可以带额外方法(如
.close()、.send()),但日常几乎用不到 - 兼容性无差别,所有 Python 版本都支持;性能上生成器略快(C 层优化),但差距微乎其微
真正容易被忽略的点:生成器函数一旦执行完毕就不可重用,而手写类如果设计成每次 __iter__() 返回新实例,就能支持多次 for ——这点很多人以为「生成器更方便」,其实反而更难复用。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










