for 循环里面的迭代器到底怎么迭代的

72 天前
 sgld

为什么会产生这个问题?

因为我写了一个有问题的代码,大概长下面这样

# 如下是一个简单的循环
l = ['abc' ,2 ,[1, 2, 3]  ,4]
for i in l:
    print(i)
    l.remove(i)
print(l)

最后的输出是

abc
[1, 2, 3]
[2, 4]

踩坑的原因是,在遍历的时候,我根据一些条件去删除列表中的元素,然后偶然发现输出与我的预期并不符合。

原本的理解是next会依次返回后面一个元素,因此现在这个元素我删了也没事。

但是事实显然不是这样,列表产生的迭代器返回值好像是根据索引返回的

大模型的回答不同模型直接存在差异,因此在翻了一些 blog ,有一篇里面有句话如下所示

==迭代器本身并不存储任何数据项,存储的只是一个指针,该指针指向可迭代对象中真正存储的数据项,它指向当前被遍历到的数据项索引位置,下一次遍历则向后推进这个位置==

所以再次来求助一下,迭代器的 next 是按照索引来获取数据的吗

2231 次点击
所在节点    Python
14 条回复
codehz
72 天前
这就是为啥要删除的话推荐用列表推导式(
实际上没几个语言能在迭代的时候修改原数组的吧(
lisongeee
72 天前
qianzanqi
72 天前
list_iterator 也就是 type(iter([]))定义在
https://github.com/python/cpython/blob/main/Include/internal/pycore_list.h#L57
成员变量是索引和原本 list

__next__逻辑在
https://github.com/python/cpython/blob/main/Objects/listobject.c#L3872
用 PyObject *item = list_get_item_ref(seq, index);获取元素,list_get_item_ref 在读取非法 index 时返回 NULL 从而结束 next 调用。执行完一次 next 后,list_iterator 储存的 index+1

你的例子中,一共调用了 2 次 next
第一次结束 index=0 list=[2, [1, 2, 3], 4]
第二次结束 index=1 list=[2, 4]
第三次调用 next 时,index=2 非法,结束迭代
qianzanqi
72 天前
@qianzanqi 说例子时的 index 错了
第一次开始 index=0 ,结束时 index=1 list=[2, [1, 2, 3], 4]
第二次开始 index=1 ,结束时 index=2 list=[2, 4]
第三次 index=2 非法
sgld
72 天前
@lisongeee 确实很清楚的 index+1 qwq
感谢大佬
sgld
72 天前
@qianzanqi 感谢大佬,源码大概意思能理解,明确指出了 index + 1 ,FT_ATOMIC_STORE_SSIZE_RELAXED 这些就去问大模型理解了,不太熟悉。
index < 0 就会返回 NUll ,item == NULL 就把 index 设置为-1 。从而退出循环
scipelaina
72 天前
cybort
72 天前
就算不用迭代器也不能一边循环一边 remove 啊
shinession
72 天前
按索引删除的话,要从最大到 0 删除,
for i in range(len(l)-1,-1,-1):
print(l[i])
l.pop(i)
print(l)
EndlessMemory
72 天前
再遍历某个可迭代对象的时候,不要做删除操作
Lhcfl
72 天前
不要写这样的代码,会跑出 O(n^2 )的时间复杂度,而且如果是 C++的话这是典型的 undefined behaviour ,以及都用 python 了研究迭代器怎么迭代的干什么,把它当成黑盒模型用就好了
julyclyde
72 天前
所谓指针这个明显是臆测啊
那只是其中一种实现方法,但并不是必须这么实现
deplives
72 天前
众所周知,遍历对象的时候不要做删除操作
delphisharp
39 天前
不要在遍历时做改变遍历对象长度的操作。会给自己挖坑的。
就仅仅做打印删除的场景,我用 while 来实现。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/1068287

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX