以下代码:
a = list(range(10))
remove = False
for b in a:
if remove:
a.remove(b)
remove = not remove
print(a)
Run Code Online (Sandbox Code Playgroud)
输出[0, 2, 3, 5, 6, 8, 9],而不是[0, 2, 4, 6, 8]使用Python 3.2时.
请注意,我不是要解决这个行为,而是要了解它.
sen*_*rle 18
我辩论了一段时间回答这个问题,因为这里有很多次问过类似的问题.但它的独特性足以让人怀疑.(不过,如果其他人投票结束,我也不会反对.)这是对正在发生的事情的直观解释.
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9] <- b = 0; remove? no
^
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9] <- b = 1; remove? yes
^
[0, 2, 3, 4, 5, 6, 7, 8, 9] <- b = 3; remove? no
^
[0, 2, 3, 4, 5, 6, 7, 8, 9] <- b = 4; remove? yes
^
[0, 2, 3, 5, 6, 7, 8, 9] <- b = 6; remove? no
^
[0, 2, 3, 5, 6, 7, 8, 9] <- b = 7; remove? yes
^
[0, 2, 3, 5, 6, 8, 9] <- b = 9; remove? no
^
Run Code Online (Sandbox Code Playgroud)
由于没有其他人,我会尝试回答你的其他问题:
为什么没有给出错误来指示底层迭代器正在被修改?
扔不禁止许多非常有效的循环结构错误,巨蟒将不得不知道很多关于这是怎么回事,它可能将不得不在运行时获取这些信息.所有这些信息都需要时间来处理.它会使Python变得更慢,只是在速度真正重要的地方 - 循环.
有关此行为的机制是否已从早期版本的Python更改?
简而言之,没有.或者至少我非常怀疑它,当然,自从我学习Python(2.4)以来,它一直表现得很好.坦率地说,我希望任何直接实现的可变序列都能以这种方式运行.谁知道更好,请纠正我.(实际上,快速的文档查找确认了Mikola引用的文本自1.4版以来一直在教程中!)
正如Mikola解释的那样,您观察到的实际结果是由于以下事实导致的:从列表中删除条目会将整个列表移动一个位置,从而导致您错过元素。
但是,在我看来,更有趣的问题是为什么python在发生这种情况时不选择生成错误消息。如果您尝试修改字典,它的确会产生这样的错误消息。我认为有两个原因。
Dict内部很复杂,而列表则没有。列表基本上只是数组。字典必须在迭代时检测其修改时间,以避免在字典的内部结构发生更改时崩溃。列表可以不做检查就可以通过,因为它只是确保其当前索引仍在范围内。
历史上,(我现在不确定),使用[]运算符来迭代python列表。Python将评估list [0],list [1],list [2],直到得到IndexError。在那种情况下,python在开始之前没有跟踪列表的大小,因此它没有检测列表大小已更改的方法。
| 归档时间: |
|
| 查看次数: |
2565 次 |
| 最近记录: |