我有一段python代码,它需要迭代字典中的所有键,循环体可能会更改字典。
试着在字典上迭代,给我RuntimeError: dictionary changed size during iteration
。搜索错误消息会将我引导至another question,其中建议的解决方案是在开始迭代之前复制密钥列表。
在我的场景中,这只是一个部分答案,因为我不仅需要迭代原始键,还需要迭代在迭代时添加的键。我需要的代码只有在没有更多的密钥被添加到字典时终止,并且它已经处理了字典中已有的任何密钥。
到目前为止,我已经想出了这个:
processed = set()
while True:
keys = set(dictionary) - processed
if not keys:
break
for k in keys:
processed.add(k)
# Do something with k
这种做法看起来确实过于复杂。有什么方法可以简化它,并且仍然可以处理添加到字典中的所有键,而不是多次处理它们吗?
在其他一些语言中,while循环的前四行可以简单地写成:
while keys = set(dictionary) - processed:
然而,这在python中不起作用。我发现a question关于在python中的while循环中使用赋值作为条件。但是所提出的答案似乎都不适用于我的情景。
答案 0 :(得分:2)
考虑相反的方法。跟踪仍需要处理的密钥,而不是已经处理过的密钥。
remaining = set(dictionary.items())
while remaining:
key, value = remaining.pop()
# process the item
if item_to_add:
dictionary[new_key] = new_value
remaining.add((new_key, new_value))
这避免了每次迭代都会产生昂贵的设置差异操作。
如果你真的不知道在处理过程中添加了哪些键,那么你问题中的代码就是好的。编写它的方式略有不同:
keys = set(dictionary)
processed = set()
while keys:
for k in keys:
# Do something with k
processed.update(keys)
keys = set(dictionary) - processed
这样更好吗?更差?我想你可以决定。
答案 1 :(得分:2)
也许您可以使用OrderedDict
代替。迭代时添加键没问题
>>> from collections import OrderedDict
>>> d = OrderedDict([(1, 2), (3, 4)])
>>> for k in d:
... if k == 1:d[5] = 6
... print(k)
...
1
3
5
您是在更新密钥还是仅添加密钥?如果更新,您需要指定是否应该再次处理密钥
答案 2 :(得分:0)
我将我的代码重写为:
processed = set()
while set(dictionary) - processed:
for k in set(dictionary) - processed:
processed.add(k)
# Do something with k
这确实复制了set(dictionary) - processed
表达式,但仍然使代码更容易阅读。