Python 的“迭代”并不是一组语法,而是一种行为约定(protocol)。
当我们在使用 for 循环、生成器、推导式或内置函数(如 sum()、max()、sorted())时,底层都在遵循同一套迭代协议。
理解迭代协议,意味着真正理解 Python 世界中“数据流动”的机制。
一、什么是迭代协议
迭代协议(Iteration Protocol)是 Python 用来统一访问序列数据的一种约定。
任何对象,只要遵守以下两条规则,就能参与迭代操作:
实现 __iter__() 方法,返回一个迭代器对象。
迭代器对象实现 __next__() 方法,每次调用返回下一个元素。
这就是所谓的“可迭代对象 + 迭代器对象”机制。
换句话说,Python 不关心对象的具体类型,只要它实现了这两个方法,就被视为“可迭代”的。这正体现了 Python 的鸭子类型(Duck Typing)思想。
二、迭代协议的执行过程
当你编写一段 for 循环时,例如:
for x in [10, 20, 30]:
print(x)解释器实际上执行了以下等价逻辑:
iter_obj = iter([10, 20, 30]) # 调用 __iter__()
while True:
try:
item = next(iter_obj) # 调用 __next__()
print(item)
except StopIteration:
break也就是说:
• iter() 触发对象的 __iter__() 方法,返回一个迭代器;
• next() 触发迭代器的 __next__() 方法,取出下一个元素;
• 当没有数据时,__next__() 抛出 StopIteration 异常,循环结束。
这个三步过程(iter → next → StopIteration)就是迭代协议的核心。
三、__iter__():迭代的入口
迭代协议从 __iter__() 开始,它告诉 Python:“我可以被迭代”。
任何实现了 __iter__() 方法的对象,都能用于 for 循环、推导式、sum() 等操作。
class Numbers:
def __init__(self, n):
self.n = n
def __iter__(self):
print("调用 __iter__(),返回一个迭代器对象")
return iter(range(self.n)) # 调用内置 range 的迭代器
for num in Numbers(3):
print(num)输出:
调用 __iter__(),返回一个迭代器对象
0
1
2此处 Numbers 自身不是迭代器,但通过实现 __iter__(),它变成了可迭代对象(Iterable)。
当执行 for 语句时,Python 会调用可迭代对象的 __iter__() 方法来生成一个新的迭代器。
四、__next__():迭代的推进
__next__() 方法定义了“下一步该返回什么数据”。它属于迭代器对象(Iterator)的职责。
示例:我们自己实现一个简单迭代器。
class Counter:
"""迭代器:从 1 递增到 n"""
def __init__(self, n):
self.current = 1
self.n = n
def __next__(self):
if self.current <= self.n:
val = self.current
self.current += 1
return val
else:
raise StopIteration
def __iter__(self):
return self # 迭代器应返回自身使用方式:
for i in Counter(3):
print(i)输出:
1
2
3Counter 同时实现了 __iter__() 和 __next__(),因此它既是可迭代对象,也是迭代器对象。
五、迭代协议的兼容机制
在 Python 2 中还没有 __iter__() 方法,因此解释器提供了一种兼容机制:若对象没有定义 __iter__(),则尝试使用 __getitem__() 从索引 0 开始连续取值,直到抛出 IndexError 为止。
例如:
class Legacy:
def __init__(self, seq):
self.seq = seq
def __getitem__(self, index):
return self.seq[index] # 旧式协议:逐项返回
for x in Legacy("abc"):
print(x, end=' ')输出:
a b cPython 内部的逻辑相当于:
try:
index = 0
while True:
value = obj[index]
...
index += 1
except IndexError:
pass这种“回退策略”确保了旧代码仍能在 Python 3 中正常工作。
六、生成器与迭代协议
生成器(generator) 是迭代协议的天然实现者。
由 yield 语句定义的函数,会自动生成一个同时具有 __iter__() 与 __next__() 的对象。
def squares(n):
for i in range(n):
yield i * i # 自动实现 __next__()
g = squares(5)
print(next(g)) # 0
print(next(g)) # 1
for val in g:
print(val) # 继续输出 4, 9, 16输出:
0
1
4
9
16生成器无需显式定义类,它的运行逻辑完全符合迭代协议:
• iter(g) 返回自身;
• next(g) 产出下一个值;
• 结束时自动抛出 StopIteration。
七、抽象基类与迭代协议
Python 的 .abc 模块定义了几个与迭代协议相关的抽象基类(ABC):
Iterable:拥有 __iter__() 方法的对象;
Iterator:既有 __iter__() 又有 __next__() 的对象。
from collections.abc import Iterable, Iterator
lst = [1, 2, 3]
it = iter(lst)
print(isinstance(lst, Iterable)) # True
print(isinstance(lst, Iterator)) # False
print(isinstance(it, Iterator)) # True输出:
True
False
True• 列表是可迭代对象,但不是迭代器。
• iter(lst) 返回的迭代器对象才具备 __next__() 方法。
八、扩展协议:反向与异步迭代
Python 还定义了若干迭代协议的扩展形式,用于特殊场景。
1、反向迭代协议
如果对象实现了 __reversed__(),就能被 reversed() 调用:
class Words:
def __init__(self, text):
self.words = text.split()
def __reversed__(self):
return reversed(self.words)
for w in reversed(Words("Python is fun")):
print(w)输出:
fun
is
Python2、异步迭代协议
在异步环境中,迭代协议也有对应形式:
__aiter__():返回一个异步迭代器;
__anext__():定义每次异步取值的逻辑。
用于 async for 循环中。
小结
迭代协议是 Python 数据访问的统一接口:无论底层数据来自列表、文件、网络流或生成器,只要遵守 __iter__() 与 __next__() 的契约,它就能与 for、sum()、map() 等语言特性无缝协作。
这正体现了 Python 的“协议化思维”:只需行为兼容,而非类型继承。
迭代协议是 Python 数据流的灵魂,它让一切“可以被遍历的事物”在同一规则下运行,实现了真正的统一与优雅。
“点赞有美意,赞赏是鼓励”
特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。
Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.