在 python 中迭代和更新列表[重复]

2024-02-03

我无法理解为什么下面的代码会无限期地出现 循环(当我不使用复制列表时)

list = ["Mohit","kumar","sffsfshfsd"]
for w in list:
    if(len(w)) > 5:
        list.insert(0,w)
    print("inside loop")

print(list)  

上面的代码打印内循环无限期地。

现在,如果代替列表,我使用如下所示的副本列表效果很好。

list = ["mohit","kumar","sffffgssddf"]

for w in list[:]:
    if len(w) > 5:
        list.insert(0,w)
    print("inside loop")

print(list)  

现在我在 python 文档中读到这是行为 我会得到,但我想了解其背后的原因。感谢在 进步。


第一个 for 循环for w in list将使用迭代器(来自iter(list)) 检索并循环列表中的每个项目。该迭代器不会立即获取整个列表 - 它是lazy,这意味着它在需要时一次只能从列表中获取一项。您可以了解这里的迭代协议 http://anandology.com/python-practice-book/iterators.html, or 这里的迭代/生成器和惰性 http://naiquevin.github.io/python-generators-and-being-lazy.html.

循环索引 0 和 1 不会执行任何操作,因为它们的字符串长度小于 6。但是,在索引 2 处,您添加"sffsfshfsd"到开始list. Now list已经增长并且索引 3 处有一些东西:"sffsfshfsd"。然后迭代继续,从下一个索引 (3) 中选取值,该值再次在开始处添加,将索引 3 处的相同值移动到索引 4...循环永远不会结束。

在你的第二个循环中w in list[:]你创建一个copy整个列表的(通过使用切片运算符 https://stackoverflow.com/questions/509211/explain-slice-notation)并迭代它。您要将项目添加到原始列表,而不是副本,因此迭代器不会触及您已添加的项目。

PS:我尝试搜索Python源代码(C语言)来证明列表迭代器实际上使用递增索引(如上所述)。我不太擅长阅读Python的源代码,但这是我发现的cpython/listobject.c https://github.com/python/cpython/blob/b879fe82e7e5c3f7673c9a7fa4aad42bd05445d8/Objects/listobject.c:

创建迭代器,将起始索引设置为 0 https://github.com/python/cpython/blob/b879fe82e7e5c3f7673c9a7fa4aad42bd05445d8/Objects/listobject.c#L2797

2797 static PyObject *
2798 list_iter(PyObject *seq)
2799 {
....
2806     it = PyObject_GC_New(listiterobject, &PyListIter_Type);
....
2809     it->it_index = 0;
....
2813     return (PyObject *)it;
2814 }

next uses it->it_index从上面开始,然后递增它 https://github.com/python/cpython/blob/b879fe82e7e5c3f7673c9a7fa4aad42bd05445d8/Objects/listobject.c#L2831

2831 static PyObject *
2832 listiter_next(listiterobject *it)
2833 {
....
2844         item = PyList_GET_ITEM(seq, it->it_index);
2845         ++it->it_index;
....
2847         return item;
....
2853 }

对我来说似乎合法?

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在 python 中迭代和更新列表[重复] 的相关文章