for 循环里面的迭代器到底怎么迭代的 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
sgld
V2EX    Python

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

  •  
  •   sgld 2024-08-27 23:00:57 +08:00 2898 次点击
    这是一个创建于 418 天前的主题,其中的信息可能已经有所发展或是发生改变。

    为什么会产生这个问题?

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

    # 如下是一个简单的循环 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 是按照索引来获取数据的吗

    14 条回复    2024-09-30 10:46:33 +08:00
    codehz
        1
    codehz  
       2024-08-27 23:16:10 +08:00
    这就是为啥要删除的话推荐用列表推导式(
    实际上没几个语言能在迭代的时候修改原数组的吧(
    qianzanqi
        3
    qianzanqi  
       2024-08-27 23:39:54 +08:00
    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
        4
    qianzanqi  
       2024-08-27 23:42:57 +08:00
    @qianzanqi 说例子时的 index 错了
    第一次开始 index=0 ,结束时 index=1 list=[2, [1, 2, 3], 4]
    第二次开始 index=1 ,结束时 index=2 list=[2, 4]
    第三次 index=2 非法
    sgld
        5
    sgld  
    OP
       2024-08-27 23:46:06 +08:00
    @lisongeee 确实很清楚的 index+1 qwq
    感谢大佬
    sgld
        6
    sgld  
    OP
       2024-08-27 23:54:35 +08:00
    @qianzanqi 感谢大佬,源码大概意思能理解,明确指出了 index + 1 ,FT_ATOMIC_STORE_SSIZE_RELAXED 这些就去问大模型理解了,不太熟悉。
    index < 0 就会返回 NUll ,item == NULL 就把 index 设置为-1 。从而退出循环
    scipelaina
        7
    scipelaina  
       2024-08-28 00:12:35 +08:00
    cybort
        8
    cybort  
       2024-08-28 00:34:32 +08:00 via Android
    就算不用迭代器也不能一边循环一边 remove 啊
    shinession
        9
    shinession  
       2024-08-28 07:34:47 +08:00   1
    按索引删除的话,要从最大到 0 删除,
    for i in range(len(l)-1,-1,-1):
    print(l[i])
    l.pop(i)
    print(l)
    EndlessMemory
        10
    EndlessMemory  
       2024-08-28 09:53:51 +08:00   1
    再遍历某个可迭代对象的时候,不要做删除操作
    Lhcfl
        11
    Lhcfl  
       2024-08-28 10:33:44 +08:00
    不要写这样的代码,会跑出 O(n^2 )的时间复杂度,而且如果是 C++的话这是典型的 undefined behaviour ,以及都用 python 了研究迭代器怎么迭代的干什么,把它当成黑盒模型用就好了
    julyclyde
        12
    julyclyde  
       2024-08-28 10:46:06 +08:00
    所谓指针这个明显是臆测啊
    那只是其中一种实现方法,但并不是必须这么实现
    deplives
        13
    deplives  
       2024-08-28 12:49:03 +08:00
    众所周知,遍历对象的时候不要做删除操作
    delphisharp
        14
    delphisharp  
       2024-09-30 10:46:33 +08:00
    不要在遍历时做改变遍历对象长度的操作。会给自己挖坑的。
    就仅仅做打印删除的场景,我用 while 来实现。
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     1008 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 22ms UTC 23:14 PVG 07:14 LAX 16:14 JFK 19:14
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86