如何对要迭代的容器进行变异?

问题描述 投票:-1回答:1

在python中,哪些容器在迭代过程中正确支持突变?

例如:

container = [1, 2, 3, 4]
for i in container:
    print(i)
    if i == 2:
        container.append(8)

输出1 2 3 4 8(列表可以在迭代过程中追加)。

但是,如果我将.append(8)替换为.remove(1),则输出将变为1 2 4(即,元素3被跳过)。似乎列表迭代是在索引之上而不是元素之上,因此在迭代过程中只能安全地删除后续列表项(而非先前列表项)。

标准库中是否有任何容器确实允许在迭代过程中添加和删除元素,其行为是:

  1. 新元素确实会迭代(与list.append一样,],
  2. 被删除的元素不会随后被迭代,
  3. 一个元素是否被迭代(或不被迭代)永远不会受到other元素的添加/删除的影响。

我想到的应用程序是事件回调的注册表。触发后,我希望这些回调能够eagerly注册或注销同一事件的其他回调。 (例如,如果我遍历了容器的临时副本,则需要等待事件第二次被触发才能使更改开始生效。)

python iteration mutable
1个回答
0
投票
您要询问的行为是所涉及的迭代器的实现细节。如您所见,list_iterator类型使用内部索引,因此删除已访问的元素会导致问题,因为它会更改列表中所有更高值的索引。

我建议您实际上并未从列表中删除任何值。而是将它们添加到另一个容器,也许是set(如果它们是可哈希的)。这假定值是唯一的。但是,如果不是这样,您可能会遇到使用任何方法将其从列表中删除的问题。

container = [1, 2, 3, 4] removed = set() for i in container: if i not in removed: # skip values that have been "removed" print(i) if i == 2: removed.add(1) # since we've already visited 1, this has no real effect removed.add(3) # this does work though, we won't print the 3 container.append(8) # additions of new elements work as normal

正如评论所建议的,该循环将打印出1248
© www.soinside.com 2019 - 2024. All rights reserved.