【问题标题】:Is it correct to append to a list while iterating over it?在迭代列表时附加到列表是否正确?
【发布时间】:2023-03-23 21:55:01
【问题描述】:

我发现我可以在迭代列表时附加到列表

lst = [1]
for i in lst:
    lst.append(i+1)
    print(i)

我可以利用这种行为吗?还是气馁?我注意到set不能这样说

lst = set([1])
for i in lst:
    lst.add(i+1)
    print(i)

错误:迭代期间大小发生变化。

【问题讨论】:

  • 好吧,这不是不允许的,但第一个循环将永远运行。
  • @timgeb 我理解循环,因为它将永远运行。它仅用于演示目的。

标签: python loops for-loop


【解决方案1】:

允许在迭代列表时追加到列表,因为列表是有序的,因此在迭代期间追加的行为是可预测的。这对于在队列中的所有其他任务完成后重试失败的任务非常有用,例如:

tasks = ['task1', 'task2']
for task in tasks:
    if task == 'task1':
        tasks.append('task1-retry')
    print(task)

这个输出:

task1
task2
task1-retry

但集合没有顺序,因此在按顺序迭代的同时将项目添加到集合中会产生不确定的效果,因此是不允许的。

【讨论】:

  • 如果我尝试以类似方式更新字典,我会收到相同的错误 (dictionary size changed)。既然字典是在 Python3 中排序的,那么这个推理不应该也适用于字典吗?
  • @rahul Python 3.7 + 保证 dicts 记住插入顺序。 (不过,RuntimeError 仍然被抛出。)
【解决方案2】:

我认为它不会起作用,因为如果列表大小发生变化,那么(?)循环项目也应该改变,例如它可能会成为无限循环或内存访问冲突。 最好这样做:

list=[1,2,7,5]
list2=[]
for i in list:
  list2.append(i+1)
  print(i)
list=list+list2

【讨论】:

  • 列表理解有什么问题? list1 += [i+1 for i in list1]
  • 为了记录,OP 的第一个 sn-p 确实会进入无限循环,如果之前没有手动杀死,最终会吃掉所有内存。
【解决方案3】:

正如其他人已经说过的那样,您将创建无限循环。但是你可以用 python 中的 break 语句来捕捉它:https://docs.python.org/2.0/ref/break.html

但是如果你用 break 捕获它,你可以将它重写到另一个循环中,只要满足你用于 break 语句的条件,它就会停止。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-09-06
    • 2020-07-26
    • 2015-01-09
    • 2013-02-17
    • 2020-10-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多