kum*_*mo2 4 python for-loop list python-2.x python-3.x
我无法理解为什么以下代码无限循环(当我不使用副本列表时)
list = ["Mohit","kumar","sffsfshfsd"]
for w in list:
if(len(w)) > 5:
list.insert(0,w)
print("inside loop")
print(list)
Run Code Online (Sandbox Code Playgroud)
上面的代码无限期地打印在循环内部.
现在,如果代替列表,我使用下面的副本列表工作正常.
list = ["mohit","kumar","sffffgssddf"]
for w in list[:]:
if len(w) > 5:
list.insert(0,w)
print("inside loop")
print(list)
Run Code Online (Sandbox Code Playgroud)
现在我已经在python文档中读到这是我将得到的行为,但我想了解它背后的原因.提前致谢.
第一个for循环for w in list将使用迭代器(from iter(list))来检索和循环列表中的每个项目.这个迭代器不会立即获取整个列表 - 它是懒惰的,这意味着它只需要一次从列表中获取一个项目.您可以在这里了解 迭代协议,或迭代/生成器和懒惰.
循环索引0和1不执行任何操作,因为它们的字符串长度小于6.但是,在索引2处,您将添加"sffsfshfsd"到开头list.现在list已经增长,并且在索引3处有一些东西:"sffsfshfsd".然后迭代继续,选择从下一个索引(3),其被再次在开始添加,移动这是在指数3至4索引值相同的值...循环永远不会结束.
在第二个循环中,w in list[:]您将创建整个列表的副本(通过使用切片运算符)并迭代它.您要将项目添加到原始列表,而不是副本,因此迭代器不会触及您添加的项目.
PS:我试图搜索Python源代码(即C)来证明列表迭代器实际上使用递增索引(如上所述).我不太熟悉Python的源代码,但这是我在cpython/listobject.c中找到的:
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 }
Run Code Online (Sandbox Code Playgroud)
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 }
Run Code Online (Sandbox Code Playgroud)
对我来说似乎合法吗?