修改Python字典,同时迭代它

假设我们有一个Python字典d ,我们正在迭代它:

 for k,v in d.iteritems(): del d[f(k)] # remove some item d[g(k)] = v # add a new item 

fg只是一些黑盒转换。)

换句话说,我们尝试添加/删除项目,而使用iteritems迭代它。

这是很好的定义? 你能提供一些参考来支持你的答案吗?

(这很明显,如果它被破坏,如何解决这个问题,所以这不是我所追求的angular度。)

Python文档页面( Python 2.7 )明确提到

在添加或删除字典中的条目时使用iteritems()可能会引发RuntimeError或无法遍历所有条目。

对于Python 3也是如此 。

这也适用于iter(d)d.iterkeys()d.itervalues() ,我会尽可能地说for k, v in d.items():我不能记得确切地说是做什么for ,但是如果实现叫iter(d) ),我不会感到惊讶。

亚历克斯·马尔泰利在这里权衡这个。

在容器上循环时更换容器(例如字典)可能不安全。 所以del d[f(k)]可能不安全。 如您所知,解决方法是使用d.items() (以遍历容器的独立副本)而不是d.iteritems() (它使用相同的基础容器)。

在dict的现有索引处修改值是可以的,但是在新索引处插入值(例如d[g(k)]=v )可能不起作用。

你不能这样做,至less用d.iteritems() 。 我试过了,Python失败了

 RuntimeError: dictionary changed size during iteration 

如果你使用d.items() ,那么它的工作原理。

在Python 3中, d.items()是字典的视图,就像Python 2中的d.iteritems() 。要在Python 3中执行此操作,请使用d.copy().items() 。 这将同样允许我们遍历字典的副本,以避免修改我们正在迭代的数据结构。

下面的代码显示这个没有很好的定义:

 def f(x): return x def g(x): return x+1 def h(x): return x+10 try: d = {1:"a", 2:"b", 3:"c"} for k, v in d.iteritems(): del d[f(k)] d[g(k)] = v+"x" print d except Exception as e: print "Exception:", e try: d = {1:"a", 2:"b", 3:"c"} for k, v in d.iteritems(): del d[f(k)] d[h(k)] = v+"x" print d except Exception as e: print "Exception:", e 

第一个例子调用g(k),并抛出一个exception(迭代期间字典改变大小)。

第二个例子调用h(k)并且不会抛出exception,但输出:

 {21: 'axx', 22: 'bxx', 23: 'cxx'} 

其中,看代码,似乎是错误的 – 我会有这样的预期:

 {11: 'ax', 12: 'bx', 13: 'cx'} 

我有一个包含Numpy数组的大字典,所以@ murgatroid99build议的dict.copy()。keys()是不可行的(尽pipe它工作正常)。 相反,我只是将keys_view转换成了一个列表,它工作正常(在Python 3.4中):

 for item in list(dict_d.keys()): temp = dict_d.pop(item) dict_d['some_key'] = 1 # Some value 

我意识到这并不是像上面的答案那样深入Python的内部工作的哲学领域,但它确实提供了一个解决问题的实际解决scheme。

我得到了同样的问题,我用下面的程序来解决这个问题。

即使您在迭代它时修改了Python列表,也可以进行迭代。 所以下面的代码将无限打印1。

 for i in list: list.append(1) print 1 

所以协同使用list和dict就可以解决这个问题。

 d_list=[] d_dict = {} for k in d_list: if d_dict[k] is not -1: d_dict[f(k)] = -1 # rather than deleting it mark it with -1 or other value to specify that it will be not considered further(deleted) d_dict[g(k)] = v # add a new item d_list.append(g(k))