网易首页 > 网易号 > 正文 申请入驻

Python:迭代协议

0
分享至

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
3

Counter 同时实现了 __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 c

Python 内部的逻辑相当于:

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
Python

2、异步迭代协议

在异步环境中,迭代协议也有对应形式:

__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.

相关推荐
热点推荐
斯诺克最新排名:吴宜泽双线飙升,成世界第13,单赛季第4!

斯诺克最新排名:吴宜泽双线飙升,成世界第13,单赛季第4!

三秋体育
2025-11-09 22:47:06
普通人学习一下穿搭也能用普通的衣服穿出高级感

普通人学习一下穿搭也能用普通的衣服穿出高级感

牛弹琴123456
2025-11-09 19:52:16
胡琏孙女祭拜聂曦,称会联系其后代看是否想公开露面,李立群表态

胡琏孙女祭拜聂曦,称会联系其后代看是否想公开露面,李立群表态

诗意世界
2025-11-08 21:58:42
一反常态!加州开始大规模吊销卡车驾照!不降级连普通驾照也吊销

一反常态!加州开始大规模吊销卡车驾照!不降级连普通驾照也吊销

大洛杉矶LA
2025-11-09 03:58:09
第一集就这么离谱,HBO的新剧上线了

第一集就这么离谱,HBO的新剧上线了

桑葚爱动画
2025-10-15 12:30:02
五年2.7亿首秀几分?福克斯24+3献决胜球 马刺三后卫先发会成常态

五年2.7亿首秀几分?福克斯24+3献决胜球 马刺三后卫先发会成常态

颜小白的篮球梦
2025-11-09 11:31:53
第93分钟绝平,凯恩绝境救主,德甲霸主爆冷,连胜终结

第93分钟绝平,凯恩绝境救主,德甲霸主爆冷,连胜终结

足球狗说
2025-11-09 00:28:14
性能高出1000倍!中国北斗被某国电磁干扰,他成功破解助北斗建成

性能高出1000倍!中国北斗被某国电磁干扰,他成功破解助北斗建成

知鉴明史
2025-11-08 14:47:21
演员张艺洋已执行死刑!中国娱乐圈首例,倪大红、李雪健被牵连

演员张艺洋已执行死刑!中国娱乐圈首例,倪大红、李雪健被牵连

阿纂看事
2025-07-25 17:12:19
中国女库里张敬一官宣:正式告别WCBA 曾单场狂轰50+16三分

中国女库里张敬一官宣:正式告别WCBA 曾单场狂轰50+16三分

醉卧浮生
2025-11-09 21:13:01
蒋介石死后,无子女的宋美龄,靠啥在美国过了28年奢华生活?

蒋介石死后,无子女的宋美龄,靠啥在美国过了28年奢华生活?

牛马搞笑
2025-11-01 09:52:48
美财长放话:一旦中国在稀土上“出尔反尔”,美国将随时准备动手

美财长放话:一旦中国在稀土上“出尔反尔”,美国将随时准备动手

国学聚焦
2025-11-09 22:29:57
中国选手3连冠!22岁吴宜泽10-6问鼎国锦赛 夺生涯首冠+奖金164万

中国选手3连冠!22岁吴宜泽10-6问鼎国锦赛 夺生涯首冠+奖金164万

风过乡
2025-11-09 22:06:13
11球5助攻 18岁国足希望星引得英超德甲豪强哄抢 留洋新旗帜出现

11球5助攻 18岁国足希望星引得英超德甲豪强哄抢 留洋新旗帜出现

零度眼看球
2025-11-09 07:05:26
老干妈放弃遵义椒始末:立善立德不立威的陶华碧输给了人性

老干妈放弃遵义椒始末:立善立德不立威的陶华碧输给了人性

诗意世界
2025-11-07 09:35:12
史诗一战!2-0打爆世界第1,26岁美女斩年终冠军 独揽奖金3728万

史诗一战!2-0打爆世界第1,26岁美女斩年终冠军 独揽奖金3728万

风过乡
2025-11-09 06:46:43
不出意外的话!苏林会成为第二个黎笋

不出意外的话!苏林会成为第二个黎笋

近史谈
2025-11-02 18:54:35
为什么建议大家使用现金支付?原因很现实,银行人员告诉你答案

为什么建议大家使用现金支付?原因很现实,银行人员告诉你答案

小俊分享
2025-10-23 21:48:21
蒋介石在日记里坦言:重庆谈判放走毛泽东,全是因为这两点!

蒋介石在日记里坦言:重庆谈判放走毛泽东,全是因为这两点!

鹤羽说个事
2025-10-25 11:44:53
真相炸裂,吴石夫人王碧奎家族齐发声,三面横幅揭开尘封百年身世

真相炸裂,吴石夫人王碧奎家族齐发声,三面横幅揭开尘封百年身世

大国纪录
2025-11-07 15:34:14
2025-11-10 00:08:49
MediaTea
MediaTea
专业的数字媒体、新媒体技术
1575文章数 64关注度
往期回顾 全部

科技要闻

黄仁勋亲赴台积电“讨要更多芯片”

头条要闻

陕西男子打晕妻子误以为已死 将人扔下土崖致其死亡

头条要闻

陕西男子打晕妻子误以为已死 将人扔下土崖致其死亡

体育要闻

他只想默默地拿走最后一亿美元

娱乐要闻

《繁花》事件影响:唐嫣工作被取消

财经要闻

10月CPI同比涨0.2% PPI同比下降2.1%

汽车要闻

钛7月销破2万 霜雾灰与青峦翠配色正式开启交付

态度原创

健康
艺术
亲子
教育
时尚

超声探头会加重受伤情况吗?

艺术要闻

心中有你,无论相见与否总是思念。

亲子要闻

小龚大夫上线了

教育要闻

高考地理中的页岩油气

伊姐周六热推:电视剧《四喜》;电视剧《唐朝诡事录之长安》......

无障碍浏览 进入关怀版