Python中遍历字典过程中更改元素导致异常的解决方法
|
先来回顾一下Python中遍历字典的一些基本方法:
#!/usr/bin/python
dict={"a":"apple","b":"banana","o":"orange"}
print "##########dict######################"
for i in dict:
print "dict[%s]=" % i,dict[i]
print "###########items#####################"
for (k,v) in dict.items():
print "dict[%s]=" % k,v
print "###########iteritems#################"
for k,v in dict.iteritems():
print "dict[%s]=" % k,v
print "###########iterkeys,itervalues#######"
for k,v in zip(dict.iterkeys(),dict.itervalues()):
print "dict[%s]=" % k,v
执行结果: ##########dict###################### dict[a]= apple dict[b]= banana dict[o]= orange ###########items##################### dict[a]= apple dict[b]= banana dict[o]= orange ###########iteritems################# dict[a]= apple dict[b]= banana dict[o]= orange ###########iterkeys,itervalues####### dict[a]= apple dict[b]= banana dict[o]= orange 嗯,然后我们进入“正题”-- 一段关于Python字典遍历的“争论”....
#这里初始化一个dict
>>> d = {'a':1,'b':0,'c':1,'d':0}
#本意是遍历dict,发现元素的值是0的话,就删掉
>>> for k in d:
... if d[k] == 0:
... del(d[k])
...
Traceback (most recent call last):
File "<stdin>",line 1,in <module>
RuntimeError: dictionary changed size during iteration
#结果抛出异常了,两个0的元素,也只删掉一个。
>>> d
{'a': 1,'c': 1,'d': 0}
>>> d = {'a':1,'d':0}
#d.keys() 是一个下标的数组
>>> d.keys()
['a','c','b','d']
#这样遍历,就没问题了,因为其实其实这里遍历的是d.keys()这个list常量。
>>> for k in d.keys():
... if d[k] == 0:
... del(d[k])
...
>>> d
{'a': 1,'c': 1}
#结果也是对的
>>>
#这里初始化一个dict
>>> d = {'a':1,'d': 0}
>>> d = {'a':1,'c': 1}
#结果也是对的
>>>
其实这个问题本来很简单,就是说如果遍历一个字典,但是在遍历中改变了他,比如增删某个元素,就会导致遍历退出,并且抛出一个dictionary changed size during iteration的异常. 首先,python 是推荐使用迭代器的,也就是 for k in adict 形式。其次,在遍历中删除容器中的元素,在 C++ STL 和 Python 等库中,都是不推荐的,因为这种情况往往说明了你的设计方案有问题,所有都有特殊要求,对应到 python 中,就是要使用 adict.key() 做一个拷贝。最后,所有的 Python 容器都不承诺线程安全,你要多线程做这件事,本身就必须得加锁,这也说明了业务代码设计有问题的. 但由“遍历中删除特定元素”这种特例,得出“遍历dict的时候,养成使用 for k in d.keys() 的习惯”,我觉得有必要纠正一下。在普通的遍历中,应该使用 for k in adict。 这个写法让我眼前一亮:怎么还有这个语法?
#!/usr/bin/env python
# -*- coding=utf-8 -*-
a = {'a':1,'d':0}
b={}
for k,v in a.items():
if v != 0:
b.update({k:v})
adict = b
del b
print a
#!/usr/bin/env python
# -*- coding=utf-8 -*-
a = {'a':1,v in a.items():
if v != 0:
b.update({k:v})
adict = b
del b
print a
不知道对不对。
val = float(raw_input("Age: "))
status = ("working","retired")[val>65]
print "You should be",status
val = float(raw_input("Age: "))
status = ("working",status
val>65是个逻辑表达式,返回0或者1,刚好作为前面那个元组的ID来取值,实在是太妙了。。。 #V1 if X else V2 s = None a = "not null" if s == None else s print a #'not null' 后来发帖在华蟒用户组(中文Python技术邮件列表)中提到后众多大神解答如下:
>>> alist = [1,2,3,4,5]
>>> alist = [i for i in alist if i != 0]
>>> alist
[1,5]
>>> d = {'a':1,'d':0}
>>> d = dict([(k,v) for k,v in d.iteritems() if v!=0])
>>> d
{'a':1,'c':1'}
如果大于Python>=2.7
>>> d = {k:v for k,v in d.iteritems() if v !=0 }
(编辑:安卓应用网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
