For循环迭代的次数少于我在Python中预期的次数

时间:2019-05-31 14:51:56

标签: python python-3.x list for-loop

我希望下面的循环迭代六次,而不是用python3迭代三遍。我不了解这种行为。 我知道列表在删除元素时会发生变化,但是我不知道那会如何影响for循环条件。 为什么循环迭代少于六次?

a = [1, 2, 3, 4, 5, 6]
for elem in a:
        del a[0]
        print(a)

3 个答案:

答案 0 :(得分:4)

您将通过del a[0]删除循环的每个迭代中的第一个元素,因此,迭代器将分3步清空,因为迭代器将在下一次迭代中删除的元素之后移至该元素。 您可以检查迭代器当前所在的元素,以及下面代码中的列表状态

a = [1, 2, 3, 4, 5, 6]
for elem in a:
    print(elem)
    del a[0]
    print(a)

输出为

1
[2, 3, 4, 5, 6]
3
[3, 4, 5, 6]
5
[4, 5, 6]

您可以将其视为指向列表中第一个元素的指针,当您在每次迭代中删除第一个元素时,该指针跳2个步骤,而6个元素只能跳3次。

通常,修改要迭代的相同列表是一个坏主意。 但是,如果确实要删除,如果您确实要删除项目,则可以遍历列表a[:]的副本

a = [1, 2, 3, 4, 5, 6]
for elem in a[:]:
    del a[0]
    print(a)

输出为

[2, 3, 4, 5, 6]
[3, 4, 5, 6]
[4, 5, 6]
[5, 6]
[6]
[]

答案 1 :(得分:2)

CPython中的list迭代器通过遍历列表的位置来工作。您可以这样认为:

def list_iter(items: list):
    index = 0
    while True:
        yield items[index]
        index += 1

换句话说,迭代提供的项为0,然后为1,然后为2,依此类推。没有预取项目-需要时从列表中查找项目。

在每个步骤中删除第一项时,该列表在每个步骤中都会缩短1。由于您从6个项目的列表开始,因此在第三次迭代中它减少到3个项目-意味着第四次迭代无法查找项目。这样,您的迭代将在三个步骤之后结束。

在每个循环中同时打印当前元素时,您会看到此信息。要可视化效果,请使用enumerate获取迭代索引。请注意,它前进了一个索引,但值也偏移了两个偏移量:

>>> a = [1, 2, 3, 4, 5, 6]
... for idx, elem in enumerate(a):
...     print(elem, 'from', a)
...     print('      ', '   '*idx, '^')
...     del a[0]
...
1 from [1, 2, 3, 4, 5, 6]
        ^
3 from [2, 3, 4, 5, 6]
           ^
5 from [3, 4, 5, 6]
              ^

在容器上进行迭代时,通常没有很好的定义。您应该改为遍历副本:

a = [1, 2, 3, 4, 5, 6]
for elem in a.copy():
    del a[0]
    print(a)

答案 2 :(得分:1)

反复遍历从列表中删除元素非常棘手。一种管理方式是反向遍历列表:

a = [1, 2, 3, 4, 5, 6]
for elem in reversed(a):
    print(a)
    del a[0]
print(a)

它将打印:

[1, 2, 3, 4, 5, 6]
[2, 3, 4, 5, 6]
[3, 4, 5, 6]
[4, 5, 6]
[5, 6]
[6]
[]