前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Python字典循环RuntimeError报错分析

Python字典循环RuntimeError报错分析

作者头像
后场技术
发布2020-09-03 14:21:16
1.4K0
发布2020-09-03 14:21:16
举报
文章被收录于专栏:后场技术

情况如上所示,当运行程序的时候,报错内容为:RuntimeError: dictionary changed size during iteration

分析

我们知道Python字典是用哈希表(hash table)实现的。哈希表是一个数组,它的索引是对键运用哈希函数(hash function)求得的。for cn_id in cn_map_info:这种方式是通过iterator遍历字典,但是在遍历中改变了他,比如增删某个元素,就会导致遍历退出,并且抛出dictionary changed size during iteration的异常。

在我们平常使用中我们知道Python是推荐使用迭代器的,也就是for k in xdict形式。其次,在遍历中删除容器中的元素,在C++ STL 和 Python等库中,都是不推荐的,因为这种情况往往说明了你的设计方案有问题,所有都有特殊要求,对应到Python中,就是要使用xdict.key()做一个拷贝。最后,所有的Python容器都不承诺线程安全,你要多线程做这件事,本身就必须得加锁,这也说明了业务代码设计有问题的。

但由"遍历中删除特定元素"这种特例,得出"遍历dict的时候,养成使用for k in d.keys()的习惯",我觉得有必要纠正一下,在普通的遍历中,我们还是应该使用for k in xdict高效Pythonic的方法。

另外,对于"遍历中删除元素"这种需求,Pythonic的做法是 xdict = {k, v for adict.iteritems() if v != 0}alist = [i for i in alist if i != 0]

Python字典实现原理:https://harveyqing.gitbooks.io/python-read-and-write/content/python_advance/python_dict_implementation.html

解决方法

解决方法是在遍历字典键值,以字典键值为依据遍历,这样改变了value以后不会影响遍历继续。

Python2解决如下:

代码语言:javascript
复制
for cn_id in cn_map_info.keys():
   if cn_id not in monitor_id_list:
       del(cn_map_info[cn_id])

for cn_id in cn_map_info.keys()这种方式是通过一个列表来依次获取每个key(cn_map_info.keys()返回的列表),所以遍历过程不会奔溃。

Python3解决如下:

代码语言:javascript
复制
for cn_id in list(cn_map_info.keys()):
   if cn_id not in monitor_id_list:
       del(cn_map_info[cn_id])

同样Python3下也是通过列表来循环所有key,跟原字典不冲突,所以遍历不会奔溃。

为什么Python3下需要需要list()操作,分析如下:

代码语言:javascript
复制
nock:lab nock$ python2.6
Python 2.6.9 (unknown, Jul 14 2015, 19:46:31)
[GCC 4.2.1 Compatible Apple LLVM 6.0 (clang-600.0.39)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> monitor_id_list = [12, 13, 14, 16, 19, 20]
>>> cn_map_info = {12: 'taiwan', 13: 'hongkong', 15: 'guizhou'}
>>> print(cn_map_info.keys())
[12, 13, 15]
>>> exit()nock:lab nock$ python3
Python 3.5.1 (default, Dec 26 2015, 18:08:53)
[GCC 4.2.1 Compatible Apple LLVM 7.0.2 (clang-700.1.81)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> monitor_id_list = [12, 13, 14, 16, 19, 20]
>>> cn_map_info = {12: 'taiwan', 13: 'hongkong', 15: 'guizhou'}
>>> print(cn_map_info.keys())
dict_keys([12, 13, 15])
>>> print(list(cn_map_info.keys()))
[12, 13, 15]

问题很简单明了Python2下xdict.keys()直接返回的就是列表,而Python3下xdict.keys()返回的是字典keys对象。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2017-10-25,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 后场技术 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 分析
  • 解决方法
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档