在迭代期间修改dict

109 views
Skip to first unread message

Yuqiu Ye

unread,
Oct 30, 2017, 9:42:04 PM10/30/17
to python-cn(华蟒用户组,CPyUG 邮件列表)






















在python中,对dict或list迭代时应避免修改被迭代对象。解决方法也很简单。但让我不解的是,为什么上述图中for循环迭代次数不同,第一个为1次,第二个为2次,如何从python原理的角度解释?我也尝试过dis模块,但是字节码真心看不懂啊。请python老鸟们解惑!

piglei

unread,
Oct 30, 2017, 10:20:05 PM10/30/17
to pyth...@googlegroups.com
- forloop 迭代一个 dict 等同于 for loop d.iterkeys()
- iterkeys() 不同于 keys(),会在每次迭代尝试返回新的 key
- 你在循环内部为字典添加了 key
- 第一次生成的 key 'aa.id' 碰巧排在 'a.id' 前面(以 python 2 的『无序』排序规则)
  - 循环直接结束
- 第二次循环的 key 'a.a.id' 碰巧排在了 'a.id' 的后面
  - 所以发生了第二次循环,产生了截图中的结果

要点:

- Python 2 的字典是无序的,所以在循环内部修改字典 key,不能保证新 key 会拍在当前 key 前面或后面,并在下次迭代被拿出来
- 如果一定要在 forloop 里面修改 dict,可以使用 .keys()

------

我上文说到的顺序你可以这样看:

In [35]: print {'aa.id', 'a.id'}
set(['aa.id', 'a.id'])

In [36]: print {'a.a.id', 'a.id'}
set(['a.id', 'a.a.id'])

2017-10-31 9:42 GMT+08:00 Yuqiu Ye <yyq...@gmail.com>:






















在python中,对dict或list迭代时应避免修改被迭代对象。解决方法也很简单。但让我不解的是,为什么上述图中for循环迭代次数不同,第一个为1次,第二个为2次,如何从python原理的角度解释?我也尝试过dis模块,但是字节码真心看不懂啊。请python老鸟们解惑!

--
邮件来自: `CPyUG`华蟒用户组(中文Python技术邮件列表)
规则: http://code.google.com/p/cpyug/wiki/PythonCn
详情: http://code.google.com/p/cpyug/wiki/CpyUg
严正: 理解列表! 智慧提问! http://wiki.woodpecker.org.cn/moin/AskForHelp
---
您收到此邮件是因为您订阅了Google网上论坛上的“python-cn(华蟒用户组,CPyUG 邮件列表)”群组。
要退订此群组并停止接收此群组的电子邮件,请发送电子邮件到python-cn+unsubscribe@googlegroups.com
要发帖到此群组,请发送电子邮件至python-cn@googlegroups.com
要查看更多选项,请访问https://groups.google.com/d/optout

王川

unread,
Oct 30, 2017, 10:26:38 PM10/30/17
to sunshine
像这种不可预期的行为应该避免才对啊,有什么好的建议吗?

piglei

unread,
Oct 30, 2017, 10:28:52 PM10/30/17
to pyth...@googlegroups.com
使用 .keys(),行为就是『可预期』的。

Yuqiu Ye

unread,
Oct 30, 2017, 11:04:00 PM10/30/17
to python-cn(华蟒用户组,CPyUG 邮件列表)
for k in d == for k in d.iterkeys() 这一点我是知道的,但是忽略了你所说的的字典无序这一点,导致我一直没想通。昨天花了一下午时间在网上找相关资料,但没有一个答案能让我信服,非常感谢你的回答!

在 2017年10月31日星期二 UTC+8上午10:20:05,猪之哀伤写道:
Reply all
Reply to author
Forward
0 new messages