迭代器协议
理解 __iter__ 和 __next__
迭代器协议 是 CoddyKit 上的免费 Python Academy 课时。 这是第 1 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Python Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Python Academy 课程共包含 4 节课。
什么是迭代
每当您对列表、字符串或字典编写 for 循环时,Python 都会在幕后使用迭代器协议。
可以进行循环访问的对象称为可迭代对象。实际负责一次生成一个值的对象称为迭代器。
for ch in 'abc':
print(ch)迭代函数与获取下一个值
两个内置函数驱动迭代:
iter(obj)会向可迭代对象请求其迭代器。next(it)会向迭代器请求下一个值。
没有更多值时,next() 会引发 StopIteration。
it = iter([10, 20, 30])
print(next(it))
print(next(it))
print(next(it))StopIteration
多调用一次 next() 就会引发 StopIteration。for 循环会自动捕获它并干净地停止。
it = iter([1])
print(next(it))
try:
next(it)
except StopIteration:
print('No more items')两个双下划线方法
要创建自己的迭代器,您需要实现两个方法:
__iter__返回迭代器对象本身。__next__返回下一个值,或者引发StopIteration。
class Count:
def __init__(self, n):
self.i = 0
self.n = n
def __iter__(self):
return self
def __next__(self):
if self.i >= self.n:
raise StopIteration
self.i += 1
return self.i
for x in Count(3):
print(x)可迭代对象与迭代器
可迭代对象只需要 __iter__。迭代器则需要同时实现 __iter__ 和 __next__。
列表是可迭代对象,但不是迭代器:每次调用 iter() 都会得到一个新的迭代器。
nums = [1, 2, 3]
print(iter(nums) is iter(nums))
it = iter(nums)
print(it is iter(it))迭代器只能耗尽一次
迭代器只能被消耗一次。到达末尾后,它会一直保持为空。若要再次循环,请创建新的迭代器。
it = iter([1, 2])
print(list(it))
print(list(it))类似范围的迭代器
让我们构建一个行为类似简单计数器的自定义迭代器。请注意,状态保存在实例中。
class EvenUpTo:
def __init__(self, limit):
self.cur = 0
self.limit = limit
def __iter__(self):
return self
def __next__(self):
if self.cur > self.limit:
raise StopIteration
value = self.cur
self.cur += 2
return value
print(list(EvenUpTo(8)))分离可迭代对象与迭代器
更清晰的设计是将容器与迭代器分开,这样容器就可以被循环访问多次。
class Bag:
def __init__(self, items):
self.items = items
def __iter__(self):
return BagIterator(self.items)
class BagIterator:
def __init__(self, items):
self.items = items
self.i = 0
def __iter__(self):
return self
def __next__(self):
if self.i >= len(self.items):
raise StopIteration
v = self.items[self.i]
self.i += 1
return v
b = Bag(['x', 'y'])
print(list(b))
print(list(b))使用带默认值的迭代获取函数
next(it, default) 会在迭代器为空时返回默认值,而不是引发 StopIteration。这对于安全地查看下一个值很方便。
it = iter([42])
print(next(it, 'done'))
print(next(it, 'done'))迭代器节省内存
迭代器一次生成一个项目,因此不需要将整个序列保存在内存中。这就是它们能够处理巨大甚至无限数据流的原因。
class Naturals:
def __init__(self):
self.n = 0
def __iter__(self):
return self
def __next__(self):
self.n += 1
return self.n
it = iter(Naturals())
print(next(it), next(it), next(it))消耗迭代器的内置函数
许多内置函数都接受任意迭代器,例如:sum、max、min、sorted、list 和 tuple。它们会不断获取值,直到出现 StopIteration。
class Count:
def __init__(self, n):
self.i = 0
self.n = n
def __iter__(self):
return self
def __next__(self):
if self.i >= self.n:
raise StopIteration
self.i += 1
return self.i
print(sum(Count(5)))
print(max(Count(5)))快速检查
检验您对迭代器协议的理解。
回顾
您学习了迭代器协议:
iter()获取迭代器;next()获取值。StopIteration表示迭代结束,而for会处理它。- 自定义迭代器需要实现
__iter__和__next__。 - 迭代器只能使用一次,并且节省内存。
接下来,您将使用 yield 让 Python 为您编写迭代器。
常见问题解答
「迭代器协议」课时是免费的吗?
是的 — 「迭代器协议」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Python Academy 课程的其余内容,请升级到 CoddyKit PRO。 Python Academy 课程共包含 4 节课。
「迭代器协议」这节课中我会学到什么?
理解 __iter__ 和 __next__ 你通过在浏览器中直接运行的动手代码来练习 Python Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 Python Academy 需要有经验吗?
无需任何先前经验。CoddyKit 上的 Python Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 1 节课,共 4 节。
「迭代器协议」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 Python Academy 课中编写并运行代码吗?
能。每节 Python Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。