第一个 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 }
对我来说似乎合法?