编辑:当我想要修改原文时,我知道迭代我的列表副本。然而,我曾经收到的关于在迭代时修改列表有什么问题的唯一解释是“它可能导致意想不到的结果”。
请考虑以下事项:
lst = ['a', 'b', 'c', 'd', 'e']
for x in lst:
lst.remove(x)
print(lst)
这是我尝试解释在迭代时修改列表时实际发生的情况。请注意,line2相当于for i in range(len(lst)):
,每次迭代时len(lst)
减少1。
len(lst)
从5开始。
当i = 0
时,我们删除lst[i] = 'a'
,lst = ['b', 'c', 'd', 'e']
。 len(lst)
减少到4。
i = 1
时,我们删除了lst[i] = 'c'
,因此lst = ['b', 'd', 'e']
len(lst)
减少到3。
当i = 2
时,我们删除lst[i] = 'e'
,lst = ['b', 'd']
。 len(lst)
减少到2。
这是我认为会引发IndexError的地方,因为i = 2
不在range(2)
中。但是,该程序只输出['b', 'd']
。是因为i
已“赶上”了len(lst)
吗?另外,到目前为止我的推理声音是什么?
答案 0 :(得分:0)
"注意,line2相当于范围内的i(len(lst))"
我认为不是 Python中的for循环使用集成的 next 函数迭代列表。所以最后你得到一个停止迭代错误,如果你正在迭代的可迭代完成,则由 next 引发。但是这个错误会被for循环自动捕获。
答案 1 :(得分:0)
您应该能够判断是否在过程中打印x,
lst = [1, 2, 3, 4, 5]
for x in lst:
print(x)
lst.remove(x)
# 1
# 3
# 5
发生的是,您首先要从列表中删除1。因为您删除了1而不是继续执行2,所以继续执行3.然后从列表中删除3。现在应用相同的过程,而不是前进到第4个,您将前进到第5个并从列表中删除该数字。所以你已经完成了迭代。
顺便说一下,for x in lst
与for x in range(len(lst))
不同,这可能是您感到困惑的地方。
在第一种情况下,python从列表中创建一个iterable,并在每次迭代时调用next
方法,因此当您到达列表末尾时,会引发StopIteration
错误,从而导致迭代过程停止。在第二种情况下,您应该明确地自己处理。这意味着,python不会从列表中创建迭代,您应该跟踪自己的位置。
我建议你阅读这篇文章,了解迭代和迭代器之间的区别以及它们是如何工作的:
答案 2 :(得分:0)
C实现位于listobject.c的listiter_next
函数中,相关行
if (it->it_index < PyList_GET_SIZE(seq)) {
item = PyList_GET_ITEM(seq, it->it_index);
++it->it_index;
Py_INCREF(item);
return item;
}
it->it_seq = NULL;
Py_DECREF(seq);
return NULL;
如果对象仍处于范围(it->it_index < PyList_GET_SIZE(seq)
)内,则返回该对象,否则返回NONE
。如果你离开1或100万并不重要,这不是错误。
以这种方式执行操作的一般原因是迭代器和迭代器可以在多个位置使用(考虑在for循环内读取的文件对象)。外环不应该与IndexError
崩溃只是因为它已经完成了事情。它不是非法的或固有的&#34;愚蠢的&#34;要改变你正在迭代的对象,只需要知道你的行为的后果。