在Python中迭代的过程中添加到双端队列?

19

我有一个Python的deque,正在进行迭代。有时在迭代过程中deque会发生变化,导致出现RuntimeError: deque mutated during iteration的错误。

如果这是一个Python列表(list)而不是deque,我可以通过使用切片(如my_list [:])来迭代列表的副本来解决问题。然而由于切片操作不能用于deque,因此我想知道处理这种情况的最pythonic的方法是什么?

我的解决方案是导入copy模块,然后迭代复制品,如for item in copy(my_deque): 这样做很好,但既然我在这里搜寻了这个主题,那么我就在这里发布帖子进行询问?


7
你为什么要在迭代deque时对其进行修改?能否展示一些代码? - thefourtheye
你期望当前迭代与对deque所做的任何修改有什么关系? - martineau
关于我为什么要修改它,这个deque是一个队列,用于在弹球机软件应用程序中保存活动模式的堆栈,而当模式正在被服务时,可能会出现其他模式开始并添加到deque中。我不介意在迭代期间调用任何已经进入的内容,或者调用任何已经被删除的内容。实际上,我希望在迭代开始时按照deque的原样进行迭代,因此需要复制。 - Brian Madden
临时防止更改是一个选项吗?那么您可以使用 threading.Lock 对象。 - Harald Thomson
2个回答

20
你可以通过创建一个列表来"冻结"它,没有必要将其复制到新的deque中。一个列表足够好了,因为你只需要用它进行迭代。
for elem in list(my_deque):
    ...
list(x) 可以从任何可迭代对象 x(包括 deque)创建列表,而且在大多数情况下,这是最符合 Python 风格的方法。
请注意,此解决方案仅在同一线程中修改 deque(即在循环内部)时有效。否则,请注意,list(my_deque) 不是原子性的,并且也在迭代 deque。这意味着,如果另一个线程在其运行时更改了 deque,则会出现相同的错误。如果您处于多线程环境中,请使用锁。

0

虽然您可以从deque创建一个列表,for elem in list(deque),但如果它是一个经常使用的函数,这并不总是最优的:特别是如果deque中有大量元素,并且您不断将其更改为array结构,那么就会有性能成本。

一种可能的替代方法是使用while循环和一些布尔变量来控制条件,而无需创建列表。这提供了O(1)的时间复杂度。


2
一个 while 循环适合在添加元素时进行破坏性迭代,但对于提问者的用例并没有太大帮助。 - user2357112

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接