的输出
d = {1: 1}
for k in d.keys():
d['{}'.format(k)] = d.pop(k)
print(d)
是{'1': 1}
。
d = {1: 1}
for k in d.keys():
d['i{}'.format(k)] = d.pop(k)
print(d)
是{'iiiii1': 1}
。这是一个错误吗?我正在运行Python 3.6.1 :: Anaconda 4.4.0 (x86_64)
。
答案 0 :(得分:18)
不,这不是错误。事实上这是explicitly documented:
键和值以任意顺序迭代,这是非随机的,在Python实现中各不相同,并且取决于字典的插入和删除历史。如果迭代了键,值和项视图而没有对字典进行干预修改,则项的顺序将直接对应。
[...]
在字典中添加或删除条目时迭代视图可能会引发
Integer
或无法迭代所有条目。
大胆强调我的。
您正在迭代密钥,同时在字典中添加和删除条目。这工作了几次迭代,然后你点击无法迭代所有条目案例并且迭代停止。
在6次添加时会触发重新调整大小,这会导致迭代失败; ' next'密钥现在已经在之前的'插槽。对于两个测试都会发生这种情况,在这两种情况下你都没有意识到它会迭代5次:
RuntimeError
它运行了5次,因为当前的>>> d = {1: 1}
>>> for i, k in enumerate(d):
... print(i)
... d['{}'.format(k)] = d.pop(k)
...
0
1
2
3
4
>>> d = {1: 1}
>>> for i, k in enumerate(d):
... print(i)
... d['i{}'.format(k)] = d.pop(k)
...
0
1
2
3
4
实现以hash table of size 8开头,并且触发了调整大小when the table is 2/3s full(您的初始dict有1个条目,5个插入使其成为{{ 1}}。当你删除一个密钥(需要正确处理哈希冲突)时,表格会被DKIX_DUMMY
entities填充。
请注意,这些都是高度依赖于实现的。在Python 3.5及之前,两个片段只迭代一次(即使您使用dict
来避免为键创建列表对象);迭代在3.6中继续,因为实现已更改,迭代现在遵循插入顺序。未来的Python版本可以自由地再次改变实现。