【问题标题】:Python for-in-loop stops iteration on list object created from for-in-loop [duplicate]Python for-in-loop停止从for-in-loop创建的列表对象的迭代[重复]
【发布时间】:2019-06-01 09:02:31
【问题描述】:

[第一个 Stack-o-flow Python 初学者用户提出的第一个问题]

我一直在尝试创建一个函数,将数字 1 附加到 10,然后在 python 列表对象中从 10 擦除到 1。 然而我成功了,我遇到了一个奇怪的 for-in 循环行为。

以下是我所做并成功的:

def a():
    li = []

    for i in range(1,11):
        li.append(i)
        print(li)

    for n in range(1,11):
        li.remove(li[-1])
        print(li)

a()

将打印:

[1]
[1, 2]
[1, 2, 3]
[1, 2, 3, 4]
[1, 2, 3, 4, 5]
[1, 2, 3, 4, 5, 6]
[1, 2, 3, 4, 5, 6, 7]
[1, 2, 3, 4, 5, 6, 7, 8]
[1, 2, 3, 4, 5, 6, 7, 8, 9]
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
[1, 2, 3, 4, 5, 6, 7, 8, 9]
[1, 2, 3, 4, 5, 6, 7, 8]
[1, 2, 3, 4, 5, 6, 7]
[1, 2, 3, 4, 5, 6]
[1, 2, 3, 4, 5]
[1, 2, 3, 4]
[1, 2, 3]
[1, 2]
[1]
[]

但是,如果我将其 for 循环的第二部分 range(1,11) 更改为 li,则迭代将停止,如下所示。

def a():
    li = []

    for i in range(1,11):
        li.append(i)
        print(li)

    for n in li:         <-------------- THIS PART
        li.remove(li[-1])
        print(li)

a()

将打印:

[1]
[1, 2]
[1, 2, 3]
[1, 2, 3, 4]
[1, 2, 3, 4, 5]
[1, 2, 3, 4, 5, 6]
[1, 2, 3, 4, 5, 6, 7]
[1, 2, 3, 4, 5, 6, 7, 8]
[1, 2, 3, 4, 5, 6, 7, 8, 9]
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
[1, 2, 3, 4, 5, 6, 7, 8, 9]
[1, 2, 3, 4, 5, 6, 7, 8]
[1, 2, 3, 4, 5, 6, 7]
[1, 2, 3, 4, 5, 6]
[1, 2, 3, 4, 5]

所以,我检查了对象 li 的长度。

def a():
    li = []
    for i in range(1,11):
        li.append(i)
        print(li)

    print("Length before passed: ", len(li))

    for n in li: <------------ THIS
        print("Length BEFORE REMOVE: ", len(li))

        li.remove(li[-1])

        print("Length AFTER REMOVE: ", len(li))
        print(li)
a()

将打印:

[1]
[1, 2]
[1, 2, 3]
[1, 2, 3, 4]
[1, 2, 3, 4, 5]
[1, 2, 3, 4, 5, 6]
[1, 2, 3, 4, 5, 6, 7]
[1, 2, 3, 4, 5, 6, 7, 8]
[1, 2, 3, 4, 5, 6, 7, 8, 9]
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Length before passed:  10
Length BEFORE REMOVE:  10
Length AFTER REMOVE:  9
[1, 2, 3, 4, 5, 6, 7, 8, 9]
Length BEFORE REMOVE:  9
Length AFTER REMOVE:  8
[1, 2, 3, 4, 5, 6, 7, 8]
Length BEFORE REMOVE:  8
Length AFTER REMOVE:  7
[1, 2, 3, 4, 5, 6, 7]
Length BEFORE REMOVE:  7
Length AFTER REMOVE:  6
[1, 2, 3, 4, 5, 6]
Length BEFORE REMOVE:  6
Length AFTER REMOVE:  5
[1, 2, 3, 4, 5] <---- And it stops here.

这里发生了什么? 为什么python for循环会在其完整循环之前停止?

非常感谢。

【问题讨论】:

  • 什么是st?我没有看到定义
  • 我糟糕的,有史以来第一个 stack-o-flow 用户。已更新。
  • 规则 #1:在遍历列表时不要从列表中删除项目。

标签: python python-3.x iteration for-in-loop


【解决方案1】:

在您的情况下,迭代停止是因为您从头开始迭代,但同时从结尾删除元素:

  • 第一次迭代以 9 个元素结束,因此循环继续到第 2 个元素。
  • 第 2 次迭代以 8 个元素结束,因此循环继续到第 3 个元素
  • ...
  • 第 5 次迭代以 5 个元素结束,没有第 6 个元素可以继续,循环结束。

这就是为什么在迭代列表时对其进行变异通常是不可取的。

【讨论】:

  • 哇。你太棒了。
【解决方案2】:

试运行一下,马上就明白了

def a():
    li = []

    for i in range(1,11):
        li.append(i)
        print(li)

    for n in li:
        print(n)
        li.remove(li[-1])
        print(li)

a()

通过删除元素会发生这种情况:

[1]
[1, 2]
[1, 2, 3]
[1, 2, 3, 4]
[1, 2, 3, 4, 5]
[1, 2, 3, 4, 5, 6]
[1, 2, 3, 4, 5, 6, 7]
[1, 2, 3, 4, 5, 6, 7, 8]
[1, 2, 3, 4, 5, 6, 7, 8, 9]
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
1
[1, 2, 3, 4, 5, 6, 7, 8, 9]
2
[1, 2, 3, 4, 5, 6, 7, 8]
3
[1, 2, 3, 4, 5, 6, 7]
4
[1, 2, 3, 4, 5, 6]
5
[1, 2, 3, 4, 5]

【讨论】:

    【解决方案3】:

    添加然后打印 10 次,删除然后打印 10 次 - 简化:

    a = []
    a.append(1)
    print(a)         # [1]
    a.pop()
    print(a)         # []
    

    您从一个空列表开始并在添加后打印 - 您从一个空列表停止并打印。

    第二个代码部分的问题是:您在迭代时修改了一个可迭代对象——这通常是个坏主意。


    如果你改变:

    def a():
        li = []
    
        for i in range(1,11):
            li.append(i)
            print(li)
    
        while(li):
            li.pop()  # same but easier - removes last element without params
            if(li):   # test if non empty
                print(li)
    

    或优化:

        for _ in  range(len(li)-1): # one less so it stops bevore removing the last elem
            li.pop()
            print(li)
    

    你会得到想要的输出。

    【讨论】:

    • 感谢您的友好回答!!!但我仍然处于列表章节的 for-in 循环中。我会尽快赶到的!!
    • 但是range(len(li)-1) 很有帮助!!再次感谢!!
    【解决方案4】:

    这是因为您从头到尾迭代列表,并且总是删除最后一个元素。由于 remove 方法会更改列表,并且 python 中的 for-in 循环会考虑这种更改,因此您遍历前五个元素并删除最后五个元素。

    我的建议是这样做:

    def a():
      li = []
    
      for i in range(1,11):
        li.append(i)
        print(li)
    
      print("Length before passed: ", len(li))
    
      # Remove the last item while has items
      while len(li):
        li.pop()
    

    【讨论】:

      猜你喜欢
      • 2011-04-12
      • 2020-11-17
      • 2015-02-12
      • 1970-01-01
      • 2021-06-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-05-03
      相关资源
      最近更新 更多