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

sgld · 2024-8-27 23:00:57 · 116 次点击
为什么会产生这个问题?

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

```python
# 如下是一个简单的循环
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 是按照索引来获取数据的吗
举报· 116 次点击
登录 注册 站外分享
9 条回复  
julyclyde 小成 2024-8-28 10:46:06

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

所谓指针这个明显是臆测啊
那只是其中一种实现方法,但并不是必须这么实现
Lhcfl 小成 2024-8-28 10:33:44

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

不要写这样的代码,会跑出 O(n^2 )的时间复杂度,而且如果是 C++的话这是典型的 undefined behaviour ,以及都用 python 了研究迭代器怎么迭代的干什么,把它当成黑盒模型用就好了
EndlessMemory 小成 2024-8-28 09:53:51

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

再遍历某个可迭代对象的时候,不要做删除操作
shinession 小成 2024-8-28 07:34:47

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

按索引删除的话,要从最大到 0 删除,
for i in range(len(l)-1,-1,-1):
  print(l)
  l.pop(i)
print(l)
cybort 初学 2024-8-28 00:34:32

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

就算不用迭代器也不能一边循环一边 remove 啊
scipelaina 小成 2024-8-28 00:12:35

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

https://github.com/brettcannon/desugar#for-
qianzanqi 小成 2024-8-27 23:39:54

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

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 非法,结束迭代
lisongeee 小成 2024-8-27 23:36:04

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

https://github.com/python/cpython/blob/08c0166ce4cd5b54ec3cd57cd48b57b9bc2e8d3c/Objects/listobject.c#L3849

https://github.com/python/cpython/blob/08c0166ce4cd5b54ec3cd57cd48b57b9bc2e8d3c/Objects/listobject.c#L3891

通过查看内部源码可知 list 的可迭代对象内部使用 index 维护当前迭代位置
codehz 初学 2024-8-27 23:16:10

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

这就是为啥要删除的话推荐用列表推导式(
实际上没几个语言能在迭代的时候修改原数组的吧(
返回顶部