码农高天解析Python迭代机制 拆解for循环底层字节码

【python】对迭代器一知半解?看完这个视频就会了。涉及的每个概念,都给你讲清楚! — 码农高天

码农高天

for循环本质上是在底层通过GET_ITER指令获取迭代器并调用next方法,因此迭代器自身必须实现返回self的__iter__方法以防止二次遍历报错。

AI-assisted summary of 【python】对迭代器一知半解?看完这个视频就会了。涉及的每个概念,都给你讲清楚! — original source. Check the original for full context.

Source published:

Key ideas

  • Python 的 for 循环在字节码层面通过 GET_ITER 指令静默获取迭代器,后续的所有元素步进操作均依赖该迭代器底层驱动。 (0:00)
  • 可迭代对象(Iterable)是无状态的容器,负责生成迭代器;迭代器(Iterator)则是记录遍历进度的有状态数据流游标。 (0:00)
  • 迭代器的 __next__() 方法在耗尽数据时必须抛出 StopIteration 异常,以此通知 for 循环平稳终止。 (5:00)
  • Python 规范要求 Iterator 本身也必须是 Iterable,只需在迭代器中实现返回 self 的 __iter__() 即可支持直接套用 for 循环。 (5:00)

Detailed notes

## Background 该视频由 YouTube 频道“码农高天”于 2023 年 10 月 10 日发布。视频简介指出,本期内容旨在系统性讲解 Python 中的迭代器及所有相关核心概念,包括可迭代对象的定义、`__iter__` 与 `__next__` 的机制理解,以及迭代器与 `for` 循环之间的底层关联。

## TL;DR 视频深入剖析了 Python 遍历机制的底层原理,系统辨析了可迭代对象(Iterable)与迭代器(Iterator)的职责边界:前者是具备生成迭代器能力的容器,后者则是记录游标进度的有状态数据流。通过解析字节码指令 `GET_ITER`,作者展示了 `for` 循环如何隐式获取迭代器并驱动 `next()` 调用,同时借助手写链表节点的实战案例,讲解了终止遍历抛出 `StopIteration` 的机制,并指明迭代器自身必须实现 `__iter__()` 返回 `self` 以满足灵活迭代的核心规范。

## Atmosphere & style 整体氛围通俗幽默且极具工程启发性,展现出一种资深开发者抽丝剥茧、拨开概念迷雾的技术教学风格。高天的讲解平实且直击痛点,在对比字节码、手写实现链表迭代器的过程中穿插着对 CPython 官方规范自相矛盾之处的生动调侃,使硬核的底层协议解析听起来轻松流畅、妙趣横生。

## Bulletin - [00:00](https://www.youtube.com/watch?v=vfQdRp_PhhQ&t=0s) Python 的 for 循环在字节码层面通过 GET_ITER 指令静默获取迭代器,后续的所有元素步进操作均依赖该迭代器底层驱动。 - [00:00](https://www.youtube.com/watch?v=vfQdRp_PhhQ&t=0s) 可迭代对象(Iterable)是无状态的容器,负责生成迭代器;迭代器(Iterator)则是记录遍历进度的有状态数据流游标。 - [05:00](https://www.youtube.com/watch?v=vfQdRp_PhhQ&t=300s) 迭代器的 __next__() 方法在耗尽数据时必须抛出 StopIteration 异常,以此通知 for 循环平稳终止。 - [05:00](https://www.youtube.com/watch?v=vfQdRp_PhhQ&t=300s) Python 规范要求 Iterator 本身也必须是 Iterable,只需在迭代器中实现返回 self 的 __iter__() 即可支持直接套用 for 循环。

## Key takeaways - [00:00](https://www.youtube.com/watch?v=vfQdRp_PhhQ&t=0s) for 循环并非仅能遍历列表等连续索引容器,字典和文件对象同样能借助迭代机制进行遍历。 - [00:00](https://www.youtube.com/watch?v=vfQdRp_PhhQ&t=0s) 可迭代对象(Iterable)是指能够逐个返回其成员的对象,核心特质是可以直接放置在 for 循环的 in 关键字后面。 - [00:00](https://www.youtube.com/watch?v=vfQdRp_PhhQ&t=0s) 迭代器(Iterator)表示一个有状态的数据流对象,可通过反复调用 next() 函数持续获取下一项数据。 - [00:00](https://www.youtube.com/watch?v=vfQdRp_PhhQ&t=0s) Iterable 需实现 __iter__() 返回迭代器,或作为 Sequence 实现 __getitem__() 满足序列协议。 - [00:00](https://www.youtube.com/watch?v=vfQdRp_PhhQ&t=0s) Iterator 的核心条件是必须实现 __next__() 方法,该方法负责返回下一个值或在到头时抛出异常。 - [00:00](https://www.youtube.com/watch?v=vfQdRp_PhhQ&t=0s) Python 字节码中执行 for 循环时会调用 GET_ITER 指令,首先从可迭代对象中提取对应的迭代器。 - [05:00](https://www.youtube.com/watch?v=vfQdRp_PhhQ&t=300s) 实现迭代器类的 __next__() 必须遵循严格的二选一逻辑:有数据则返回,没有数据则必须 raise StopIteration。 - [05:00](https://www.youtube.com/watch?v=vfQdRp_PhhQ&t=300s) 开发者常在用 iter() 提取迭代器并手动 next() 消费部分元素后继续用 for 循环遍历剩余部分,这要求迭代器必须可迭代。 - [05:00](https://www.youtube.com/watch?v=vfQdRp_PhhQ&t=300s) 若迭代器未实现 __iter__(),直接传入 for 循环时会抛出 TypeError: 'NodeIter' object is not iterable。 - [05:00](https://www.youtube.com/watch?v=vfQdRp_PhhQ&t=300s) 让 Iterator 成为 Iterable 的标准写法是在迭代器内部定义 def __iter__(self): return self。 - [05:00](https://www.youtube.com/watch?v=vfQdRp_PhhQ&t=300s) CPython 官方文档虽然规定每一个迭代器都必须是可迭代的,但其标准库底层实现中偶尔也存在违背此规则的特例。 - [05:00](https://www.youtube.com/watch?v=vfQdRp_PhhQ&t=300s) 日常开发的核心在于理清容器(Iterable)与状态机游标(Iterator)的职责边界,避免混淆 iter 与 next 的职能。

## Detailed walkthrough ### [00:00](https://www.youtube.com/watch?v=vfQdRp_PhhQ&t=0s) for 循环与可迭代对象:表象背后的底层机制

在 Python 中,`for` 循环和迭代器是关系极其紧密但经常被初学者混淆的概念。直观来看,一个简单的列表(`list`)遍历非常符合直觉,因为列表是有序的数据结构,可以从第 0 个、第 1 个、第 2 个逐个提取;然而,并不按数字下标排列的字典(`dictionary`),甚至更为复杂的文件对象,为什么同样能够直接套用 `for... in` 结构进行遍历?这背后依赖于 Python 的两大约束机制:**可迭代对象(Iterable)**与**迭代器(Iterator)**。根据官方文档的定义,可迭代对象是能够逐个返回其成员的对象(如 `list`、`string`、`tuple`、`dict` 等),它最核心的特质就是必须能放在 `for` 循环中 `in` 关键字的后面;而迭代器则是一个表示数据流的对象,可以通过反复调用 `next()` 函数持续从中取出新数据。

```mermaid flowchart TD accTitle: Python for loop 与迭代器工作流程 accDescr: 展示 for 循环在字节码层面如何通过 iter 获取迭代器并循环调用 next 提取数据 subgraph IterableFlow["可迭代对象 (Iterable)"] A["Iterable 对象 (如 list, dict, 文件)"] -->|"实现 __iter__() 或 __getitem__()"| B["iter(obj) 调用 / 字节码 GET_ITER"] end

subgraph IteratorFlow["迭代器 (Iterator)"] B --> C["Iterator 数据流 (有状态)"] C -->|"调用 next()"| D{"是否还有下一个数据?"} D -->|"是"| E["返回元素并推进一步"] D -->|"否"| F["抛出 StopIteration 异常"] end

subgraph ForLoop["for 循环执行"] E -->|"赋值给循环变量"| G["执行循环体代码"] G -->|"继续请求"| C F -->|"捕获异常"| H["正常结束循环"] end ```

从更高的抽象层次(high-level)来看,两者的分工界限极其清晰: - **Iterable(可迭代对象)** 更像是一个容器或数据的保存者,它本身可以是无状态的,完全不需要知道当前数到了哪一个元素,但它必须具备生成一个迭代器的能力。在底层实现上,它要么实现 `__iter__()` 方法,要么属于 Sequence 并实现 `__getitem__()` 方法,从而确保在被内置函数 `iter()` 作用时能顺利返回一个迭代器。 - **Iterator(迭代器)** 则必定是有状态的游标,记录着遍历的进度,但它不需要去实现容器的修改接口。在底层实现上,它必须实现 `__next__()` 方法,以保证被 `next()` 作用时能吐出下一个值。

通过观察 Python 程序的字节码(bytecode)可以发现,在 `LOAD_NAME` 之后紧接着执行的就是一条 `GET_ITER` 指令。也就是说,无论代码表面写得多简单,当解释器执行 `for x in iterable` 时,“所有的 for loop 的实现都是这样的:for loop 首先悄悄的做了一个从 iterable 里面拿到 iterator 的操作”,后续的所有实际步进都是基于该迭代器在底层驱动的。

- **Iterable 核心条件**:实现 `__iter__()` 返回迭代器,或实现 `__getitem__()` 满足序列协议。 - **Iterator 核心条件**:必须实现 `__next__()`,在调用时返回数据流中的下一项。 - **for 循环底层指令**:通过 `GET_ITER` 字节码从栈顶的可迭代对象中提取对应的迭代器。

---

[05:00](https://www.youtube.com/watch?v=vfQdRp_PhhQ&t=300s) 手写链表迭代器与为什么迭代器自身也必须是 Iterable

为了彻底掌握底层原理,码农高天以 Python 中没有内置但在算法中极其常见的“链表(Linked List)”为例,手写了一个可迭代的 `Node` 类及其配套的迭代器 `NodeIter`。实现一个迭代器类的 `__next__()` 时,开发者在逻辑上必须严格二选一:“第一,如果你这个 iterator 已经到头了,没有办法再给出数据了,你需要 raise 一个 StopIteration 这个 exception;第二,如果还有数据的话,把这个数据 return 回去。”在具体实现中,通过维护 `self.curr_node` 追踪当前节点,如果为 `None` 则抛出 `StopIteration`,否则将指针前移一位并返回当前节点。而在 `Node` 类中定义 `__iter__()` 并返回 `NodeIter(self)`,即可让整个链表顺畅地运行在 `for node in node1:` 的循环中,正确打印出链表各节点的名称。

很多教程和规范都强调 Iterator 除了 `__next__()` 之外还必须实现 `__iter__()`,高天在此解释了背后的根本原因。如果在遍历前需要手动跳过特定元素,开发者很可能会先写 `it = iter(node1)` 手动调用一次 `next(it)` 取出首节点,随后直接写 `for node in it:` 遍历剩余部分。如果迭代器没有实现 `__iter__()`,Python 就会直接抛出类型错误(`TypeError: 'NodeIter' object is not iterable`)。这种写法在逻辑上非常自然,报错却反直觉,因此 Python 官方文档规定:**迭代器本身也必须是一个可迭代对象**。其实现方式极其简单,只需在迭代器类中添加两行代码,让其 `__iter__()` 直接返回 `self` 即可:

```python class NodeIter:

def __init__(self, start_node): self.curr_node = start_node

def __next__(self): if self.curr_node is None: raise StopIteration node = self.curr_node self.curr_node = self.curr_node.next return node

def __iter__(self): return self # 返回自身,使迭代器同时也是 Iterable ```

有趣的是,官方 CPython 文档在制定此规则的同时,甚至自嘲地加了一句附注,承认 CPython 本身也并不总是遵循“每一个 iterator 都必须是 iterable”的铁律,引得高天调侃道:“你说这些人讨厌不讨厌,自己定了一个要求自己不遵守。”但针对日常工程开发,高天亮明了自己的观点: > “我的观点是,首先最好写,因为这件事很简单就两行代码;但是更重要的应该是你应该知道 `iter` 这个函数是干嘛的,`next` 这个函数是干嘛的,他们俩有什么区别,也就是你要分清什么是 Iterable,什么是 Iterator,这两个东西是不一样的。”

只要从本质上理清了容器与状态机的职责差异,面对各种复杂数据结构时,究竟谁该写 `__iter__`、谁该写 `__next__`,便能一目了然。

- **迭代终止协议**:迭代器遍历完毕后必须主动 `raise StopIteration`,`for` 循环捕获该异常后平稳退出。 - **让 Iterator 成为 Iterable 的通用写法**:定义 `def __iter__(self): return self`,使其能无缝传给 `for` 循环、`zip()`、`map()` 等接收 Iterable 的接口。 - **CPython 实现细节**:虽然官方规范要求迭代器实现 `__iter__`,但标准库或 C 底层代码中仍存在极个别未完全遵循此规则的遗留特例。

## Notable quotes > [00:00](https://www.youtube.com/watch?v=vfQdRp_PhhQ&t=0s) 所有的 for loop 的实现都是这样的:for loop 首先悄悄的做了一个从 iterable 里面拿到 iterator 的操作 — 码农高天

> [05:00](https://www.youtube.com/watch?v=vfQdRp_PhhQ&t=300s) 你应该知道 `iter` 这个函数是干嘛的,`next` 这个函数是干嘛的,他们俩有什么区别,也就是你要分清什么是 Iterable,什么是 Iterator,这两个东西是不一样的。 — 码农高天

## Mentioned 码农高天, Python, CPython

## Video description 这期视频讲一下迭代器以及所有相关的概念,包括什么叫可迭代对象,__iter__和__next__的理解,以及迭代器和for loop的关系。

[Source](https://www.youtube.com/watch?v=vfQdRp_PhhQ)

中文简报

码农高天解析Python迭代机制 拆解for循环底层字节码 for循环本质上是在底层通过GET_ITER指令获取迭代器并调用next方法,因此迭代器自身必须实现返回self的__iter__方法以防止二次遍历报错。 视频深入剖析了 Python 遍历机制的底层原理,系统辨析了可迭代对象(Iterable)与迭代器(Iterator)的职责边界:前者是具备生成迭代器能力的容器,后者则是记录游标进度的有状态数据流。通过解析字节码指令 GET_ITER,作者展示了 for 循环如何隐式获取迭代器并驱动 next() 调用,同时借助手写链表节点的实战案例,讲解了终止遍历抛出 StopIteration 的机制,并指明迭代器自身必须实现 __iter__() 返回 self 以满足灵活迭代的核心规范。 Python 的 for 循环在字节码层面通过 GET_ITER 指令静默获取迭代器,后续的所有元素步进操作均依赖该迭代器底层驱动。 (0:00) 可迭代对象(Iterable)是无状态的容器,负责生成迭代器;迭代器(Iterator)则是记录遍历进度的有状态数据流游标。 (0:00) 迭代器的 __next__() 方法在耗尽数据时必须抛出 StopIteration 异常,以此通知 for 循环平稳终止。 (5:00) Python 规范要求 Iterator 本身也必须是 Iterable,只需在迭代器中实现返回 self 的 __iter__() 即可支持直接套用 for 循环。 (5:00)

Reading summary

码农高天指出,Python 的 `for` 循环底层统一依赖“可迭代对象(Iterable)”与“迭代器(Iterator)”的协作机制,二者分别承担容器存储与状态步进的职责。 for 循环底层与双重概念分工 (0:00) 在 Python 中,无论是连续索引的列表,还是非数字下标的字典与文件对象,均可直接应用于 `for... in` 语句。高天通过字节码分析说明,执行 `for x in iterable` 时,解释器在 `LOAD_NAME` 后紧接着执行 `GET_ITER` 指令,这一步骤悄悄将可迭代对象转化为迭代器,后续的实际数据拉取完全交由迭代器驱动。 从抽象职责来看,可迭代对象(Iterable)扮演容器或数据持有者的角色,本身可以是无状态的,核心要求是能够响应 `iter()` 调用并返回迭代器,底层需实现 `__iter__()` 或基于序列协议实现 `__getitem__()`。迭代器(Iterator)则是有状态的游标,仅负责记录推进位置并通过 `__next__()` 持续产出数据流,无需具备容器修改接口。 迭代终止协议与链表迭代器实现 (5:00) 高天以自定义链表结构为例,演示了 `Node` 容器类与 `NodeIter` 迭代器类的构建方式。实现迭代器的 `__next__()` 方法时存在严格的二选一逻辑:若数据流已耗尽,必须主动抛出 `StopIteration` 异常;若仍有数据,则更新内部指针(如 `self.curr_node`)并返回当前元素。外层的 `for` 循环依靠捕获 `StopIteration` 异常来平稳终止,由此完成非内置数据结构向标准遍历语法的接入。 迭代器兼具 Iterable 的工程规范 (5:00) 在实际开发中,开发者常通过 `iter()` 获取迭代器并调用 `next()` 消费部分数据,随后希望将其直接传入 `for` 循环遍历剩余内容。若迭代器未实现 `__iter__()` 方法,此类操作会触发 `TypeError: 'NodeIter' object is not iterable` 报错。为了兼顾这种自然的编程逻辑,Python 规范要求迭代器自身也必须是可迭代对象,其标准写法是在迭代器类中添加 `def __iter__(self): return self`。 虽然官方 CPython 文档注记承认底层存在极少数未遵守此规则的特例,但高天主张在日常工程中应主动补充这两行代码。更关键的在于厘清 `iter()` 与 `next()` 的职责边界,准确把握容器协议与数据流状态机的本质差异。 理解 Iterable 与 Iterator 的分工不仅解释了各种数据结构支持 `for` 循环的底层原理,也明确了自定义类中 `__iter__` 与 `__next__` 的编写规范与终止异常处理。

Source quotes

[0:00] 码农高天: 所有的 for loop 的实现都是这样的:for loop 首先悄悄的做了一个从 iterable 里面拿到 iterator 的操作 [5:00] 码农高天: 你应该知道 `iter` 这个函数是干嘛的,`next` 这个函数是干嘛的,他们俩有什么区别,也就是你要分清什么是 Iterable,什么是 Iterator,这两个东西是不一样的。

Original transcript

[0:00] 这期视频我们讲一些for loop和迭代器那在之前视频里呢 我们其实不太常把两个概念一起来聊但是在π当中这两个概念确实关系非常紧密所以咱们今天就一块说了大家看我左边写了一个非常简单的for loop 对不对只要你会一点点python 你就能知道这个程序在干嘛有的人可能觉得这件事很符合直觉对不对但是有的人呢比如说你可能之前学过其他的语言或者是你这个深入的考虑过它是怎么实现的你就会发现这个事儿并不简单对吧list本身是一个有序的结构 你一个一个拿的话可以是第0个 第1个 第2个 这个事比较符合直觉但是我们知道 dictionary也可以这么用那dictionary可不是按顺序的d0给你摆在这儿,d2给你摆在这儿的,对不对?它怎么也可以用这个full in的结构呢甚至包括在拍葬中打开的文件都可以用full in的结构那我们知道文件肯定是一个相对来说比较复杂的数据结构了对吧他肯定也不是给你标好的第0个第1个第2个它怎么也能这么用呢那我们今天就来揭示这件事背后的秘密在for loop的实现背后有两个核心概念一个叫可迭代对象一个叫迭代器英文分别是iterable跟iterator我们先来看一下python官网上给这两个词下的定义那iterable也就是可迭代对象 它说的是一个对象 然后可以一个一个的返回它的成员他给了一些例子对吧,比如说 list, string, tuple,包括 dictionary然后还特别强调了 这个iterable可以在for loop里面使用当然确切的说是for loop里面in后面那个东西必须是一个iterable也就是必须是一个可谐的对象这件事不难理解对吧 因为for loop就是在那个对象里面一个一个拿出他的成员来他们俩的定义几乎是完全重合的这也是为什么我们要把full loop跟可叠来对象放到一起讲那我们再看Iterator也就是迭代替EaterWater是一个表示数据流的对象你可以使用next 谈数不断的从对象里面获取新的数据那这两个概念确实有很多相似的地方但是如果你想把这块的理论全都搞明白的话你就必须要分清他们俩有什么区别从一个high level的角度看 一个iterable更像是一个数据的保存者 一个container它是可以没有状态的 它可以完全不知道你这个iterator数到哪了它需要有能力产生一个Iterator而Iterator一定是有状态的但是它并不需要实现一个container他当然内部肯定知道他代表这个Iterable里面是什么数据但是他不用实现一个interface 不用实现一个接口来修改这个Iterable里面的数据从实现上看 一个iterable要么就有下阔线 下阔线 iter method要不然它就需要是一个sequence然后有getItem这个method这两者都是为了保证它可以在iter这个函数的作用下返回一个iterator而 iterator 必须要有下锅线下锅线 next method这个method保证它在被next作用的时候可以返回下一个iterble里面的值我们看一下这条程序的bytecode在load name之后,他做了一个get iter而getEther这个bycode就是从站顶的iterable里面拿出来它所对应的iterator所有的full loop的实现都是这样的所以你可以理解为当你写一个for什么in 一个iterable的时候for loop首先悄悄的做了一个从iterable里面拿到iterator的操作你可以把它想象成左边这个样子但实际上不是这样的因为你在做full root的时候它还会对it进行一次Ether的一个操作但你脑子里要有个概念 在进行for loop之前 这个iterable会先被取一个iterator的值然后这个for loop是根据这个Iterator来进行操作的那有的人可能会问对吧说我知道这个有什么用呢除了让你理解python究竟在底层是怎么工作的之外你有的时候有可能会需要自己写一个iterable或者iterator我们举一个很简单的例子啊就是链表linked list那我们知道python里是没有这种内置的术语结构的但是这种术语结构又非常常见如果我们想在for loop里面使用链表的话那我们就要自己把链表变成一个iterable那我左边就实现了一个最简单的链表跟它的Iterator这个链表呢就是有一个名字然后有一个nets指针对吧然后我给他写了一个IteratorClass大家还记得我们之前讲的吧IterateClack最核心的部分是要有next函数每次调用这个next函数的时候 你需要在两件事中选择一个 [5:00] 第一如果你这个Iterator已经到头了 没有办法再给出数据了你需要rate一个stop iteration这个exception第二 如果你还有数据的话 把这个数据return回去在我的实现里 我用self.kernode表示现在已经数到哪一个node了如果self.curlnote是none的话就说明已经没了我就raise stop iteration否则的话我就往前进一个然后把现在这个node的返回回去我们看这个node的iter就是一个iterator 它实现了next参数那node就是一个iterable他实现了这个 iter函数返回node iter的一个object那在下面我也做了一个简单的测试建立了三个node然后node1的下一个是node2node2的下一个是node3这里我用了for node in node1因为每一个node都是eterble最开始那个node就是链表的表头然后我for node in node1 打印node name运行一下我们看他很成功的打印出了node1node2node3这就是我们自己实现的一个比较简单的 一个数据结构好 可能很多人看到这里会产生一个疑问就是我看到的所有教程里这个Iterator除了Next函数之外 还要实现这个Iter函数为什么你这里没实现呢我们看回python的官方文档官方文档这也说 说 iterator必须要有这个 当然他也把这么规定的原因写明白了他说 这么做是为了让每一个Iterator也是Iterable就是让每一个迭代器也是可迭代的我们来看一下为什么它这么要求我们把代码往上拉一点现在25行是for node in node1对吧我们刚才说过实际上它是先管node1要了一个iterator但是有的时候有人可能这么写他直接把这个node1显示着求了他的iterator当然这么看可能有些别扭对吧我们换一个实际上有可能真的会出现的写法我们看一下这条程序啊他是想第一个node不要从第二个开始打当然他也可以通过刚才的for loop实现当然他就想用iterator他先拿到了node1的iterator然后从里面拿到了一个值再对这个Iterator做一个Full loop看起来应该是一个挺合理的逻辑对不对我们运行一下可以看到这块就报错了为什么会报错呢 因为在我们做forNodeInIt的时候 这个it本身虽然它是个Iterator 但它不是一个Iterable 所以它不能放到forLoop里 可是这件事说实话比较反直觉就是你怎么琢磨怎么都不对因此 Python官方规定说你这个 iterator 本身必须要是一个 iterable这样你把它放到for loop里或者放到一些其他的需要eterable像zip map这些函数里面都能用这才是一个比较符合直觉的概念那实现的方式其实也很简单 对于Iterator本身来说 几乎所有情况下 你只需要定义一个Iter函数返回Self就可以了就是当你对这个Iterator求他的Iterator的时候就是他自己那让我们再运行一下刚才有点程序我们看结果已经和我们想要的一样了当然了如果你看回C派堂文档的话你会发现它下面写了一行话叫做cpython本身也并不总是遵循每一个iterator都是iterable的要求你说这些人讨厌不讨厌自己定了一个要求自己不遵守那对于Iterator到底需不需要有Iter这个函数或者是需不需要iterable这个事我的观点是首先最好写因为这件事很简单就两行代码但是更重要的应该是你应该知道iter这个函数是干嘛的next这个函数是干嘛的 他们俩有什么区别也就是你要分清什么是Iterable 什么是Iterator这两个东西是不一样的如果你能理解他们两个有什么区别那到底谁要写next函数谁要写iter函数就非常一目了然了好 那我们这期视频就到这里 希望大家有所收获如果你喜欢这期视频的话 别忘了点一下关注 记得一键三连哦优优独播剧场——YoYo Television Series Exclusive