首页 新闻 会员 周边 捐助

可迭代对象(Iterable) 例如 list、tuple、set、str 等,它们每次调用 iter(x) 都会新建一个独立的迭代器,所以可以被反复遍历。

0
[已关闭问题] 关闭于 2025-09-10 06:02

伪代码

可迭代对象(Iterable)
例如 list、tuple、set、str 等,它们每次调用 iter(x) 都会新建一个独立的迭代器,所以可以被反复遍历。

_java_python的主页 _java_python | 小虾三级 | 园豆:984
提问于:2025-09-10 06:00
< >
分享
所有回答(1)
0

每次被 iter() 调用就生成一个新的迭代器实例。

class list:                       # 伪代码
    def __iter__(self):
        # 新建一个专属的 list_iterator,把当前列表引用塞进去
        return list_iterator(self)

    def __getitem__(self, idx):
        ...                       # 正常按下标访问元素


下面用“伪代码”把 list 在 CPython 里“怎么做到多次迭代”的核心机制画出来。
真正的代码在 C 里(Objects/listobject.c),但逻辑可以这么理解:
----
1. 可迭代对象(list)只干一件事:
每次被 iter() 调用就生成一个新的迭代器实例。
class list:                       # 伪代码
    def __iter__(self):
        # 新建一个专属的 list_iterator,把当前列表引用塞进去
        return list_iterator(self)

    def __getitem__(self, idx):
        ...                       # 正常按下标访问元素

----
2. 迭代器(list_iterator)才记住“我走到哪了”:
class list_iterator:
    def __init__(self, lst):      # lst 就是外面的那个 list 对象
        self.lst = lst            # 保留对列表的引用
        self.index = 0            # 只有我自己拥有的游标

    def __iter__(self):
        return self               # 协议要求

    def __next__(self):
        if self.index >= len(self.lst):
            raise StopIteration
        val = self.lst[self.index]   # 去真正的列表里拿元素
        self.index += 1
        return val

----
3. 使用场景拆解
>>> nums = [10, 20, 30]     # 这是一个可迭代对象
>>> it1 = iter(nums)        # 第一次:list.__iter__() 返回新的 list_iterator
>>> it2 = iter(nums)        # 第二次:又返回一个全新的 list_iterator
>>> next(it1)
10
>>> next(it2)               # it2 从 0 开始,不受 it1 影响
10

•  nums 本身没有任何“游标”状态,所以可以被无限次 iter()。
•  真正消耗迭代进度的是 list_iterator 里的 index 字段;
每次 for x in nums: 都会拿到一个崭新的 list_iterator,于是又能从头再来。
----
4. 小结一句话
“可迭代对象”只负责生迭代器;
“迭代器”才负责记进度;
把“生迭代器”和“记进度”拆成两个对象,就天然支持了“多次迭代”。
_java_python | 园豆:984 (小虾三级) | 2025-09-10 06:02
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册