use*_*109 5 python dictionary for-loop python-3.x python-internals
的输出
d = {1: 1}
for k in d.keys():
d['{}'.format(k)] = d.pop(k)
print(d)
Run Code Online (Sandbox Code Playgroud)
是{'1': 1}.的输出
d = {1: 1}
for k in d.keys():
d['i{}'.format(k)] = d.pop(k)
print(d)
Run Code Online (Sandbox Code Playgroud)
是{'iiiii1': 1}.这是一个错误吗?我运行Python 3.6.1 :: Anaconda 4.4.0 (x86_64).
Mar*_*ers 18
不,这不是一个错误.事实上这是明确记录的:
键和值以任意顺序迭代,这是非随机的,在Python实现中各不相同,并且取决于字典的插入和删除历史.如果迭代键,值和项视图而没有对字典的干预修改,则项的顺序将直接对应.
[...]
在字典中添加或删除条目时迭代视图可能会引发
RuntimeError或不能遍历所有条目.
大胆强调我的.
您正在迭代密钥,同时在字典中添加和删除条目.这工作了几次迭代,然后你遇到了无法迭代所有条目情况并且迭代停止.
会发生的是你在6次添加时触发重新调整大小,这会导致迭代在那时失败; 'next'键现在位于'较早'的插槽中.这两种测试都会发生这种情况,你只是没有意识到它在两种情况下都会迭代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
Run Code Online (Sandbox Code Playgroud)
它运行5次,因为当前dict实现以大小为8的哈希表开始,并且当表是2/3s满时触发调整大小(您的初始字典有1个条目,5个插入使它> (8 * 2/3 == 5.333333).表格正在填充删除键时输入的DKIX_DUMMY实体(需要正确处理哈希冲突).
请注意,这都是高度依赖于实现的.在Python 3.5及之前,两个片段只迭代一次(即使您使用for k in d:以避免为键创建列表对象); 迭代在3.6中继续,因为实现已更改,迭代现在遵循插入顺序.未来的Python版本可以自由地再次改变实现.