Python:循环删除故障的列表索引

Python: List indexing for loop deletion glitch

这是一个很难解释的问题。我正在研究 Python 的列表方法,尤其是 del 索引对象。我想创建一个简单的脚本,它会创建一个从 1 到 100 的整数列表,然后是一个 for 循环,它会从列表中删除奇数。

这是我写的脚本:

def main():
    num = list(range(1,101))
    print(num)
    for i in range(0,101):
        del num[i]
    print(num)
main()

好像行得通吧?我也是这么想的,直到我运行它。

我不确定为什么,但是当 i 传递给 del num[i] 索引时,数字本身翻了一番。

当我运行它的时候,我收到了IndexError: list assignment index out of range

当我把参数从range(0,101)改成range(0,10)的时候,发现把1到20的奇数都删掉了

换句话说,指数中的 i 在不应该的情况下翻了一番。我能得到一些关于这方面的信息吗?

当您删除项目时,列表的大小会减小。大约 50 次循环迭代后,列表中有大约 50 项,因此嵌套迭代尝试删除列表外的内容。

这是模拟的 运行:

>>> a = [1, 2, 3, 4, 5]
>>> a
[1, 2, 3, 4, 5]
>>> del a[0]
>>> a
[2, 3, 4, 5]
>>> del a[1]
>>> a
[2, 4, 5]
>>> del a[2]
>>> a
[2, 4]
>>> del a[3]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
IndexError: list assignment index out of range

你遍历从 0 到 101 的范围,并在每次迭代中从 num 中删除一项,所以 num 的长度正在减少,你最终得到一个 索引错误.

当您在 for 循环中使用 del 关键字时,它会将项目从您创建的原始 num 列表中完全删除。通过这样做,您的列表的长度随着循环的每次迭代而变得越来越小。

这也解释了为什么它只删除奇数,因为每次删除后索引都会向下移动,从而允许偶数从程序的裂缝中溜走:

num = range(1, 5)  # num = [1, 2, 3, 4]
del num[0]  # results in num = [2, 3, 4]
del num [1]  # deletes 3, and num now = [2, 4]
etc. for a longer loop

要删除奇数,请考虑使用条件检查 %2 == 0 状态和 list.remove() 方法:

num = range(1, 101)
for i in num:
    if i % 2 != 0:
        num.remove(i)
print(num)

或者 main() 函数中的列表理解:

return [x for x in num if x % 2 == 0]

这个问题与 mutating a list 非常相似,同时遍历同一个列表,通过下面的 link 可以帮助您更好地理解这种情况。

http://gsb-eng.com/why-python-list-mutation-is-not-a-good-idea/

对于第二个 for 循环,您应该使用总索引的一半,因为在第 50 次迭代时,将删除 50 个元素,因此列表的总索引减少到 50,因此在第 51 次迭代时,它显示超出范围的错误。