Python中遍歷字典過程中更改元素導(dǎo)致異常的解決方法
先來回顧一下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
執(zhí)行結(jié)果:
##########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
嗯,然后我們進入“正題”--
一段關(guān)于Python字典遍歷的“爭論”....
先摘抄下:
#這里初始化一個dict >>> d = {'a':1, 'b':0, 'c':1, 'd':0} #本意是遍歷dict,發(fā)現(xiàn)元素的值是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 #結(jié)果拋出異常了,兩個0的元素,也只刪掉一個。 >>> d {'a': 1, 'c': 1, 'd': 0} >>> d = {'a':1, 'b':0, 'c':1, 'd':0} #d.keys() 是一個下標(biāo)的數(shù)組 >>> 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} #結(jié)果也是對的 >>> #這里初始化一個dict >>> d = {'a':1, 'b':0, 'c':1, 'd':0} #本意是遍歷dict,發(fā)現(xiàn)元素的值是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 #結(jié)果拋出異常了,兩個0的元素,也只刪掉一個。 >>> d {'a': 1, 'c': 1, 'd': 0} >>> d = {'a':1, 'b':0, 'c':1, 'd':0} #d.keys() 是一個下標(biāo)的數(shù)組 >>> 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} #結(jié)果也是對的 >>>
其實這個問題本來很簡單,就是說如果遍歷一個字典,但是在遍歷中改變了他,比如增刪某個元素,就會導(dǎo)致遍歷退出,并且拋出一個dictionary changed size during iteration的異常.
解決方法是遍歷字典鍵值,以字典鍵值為依據(jù)遍歷,這樣改變了value以后不會影響遍歷繼續(xù)。
但是下面又有一位大神拋出高論:
首先,python 是推薦使用迭代器的,也就是 for k in adict 形式。其次,在遍歷中刪除容器中的元素,在 C++ STL 和 Python 等庫中,都是不推薦的,因為這種情況往往說明了你的設(shè)計方案有問題,所有都有特殊要求,對應(yīng)到 python 中,就是要使用 adict.key() 做一個拷貝。最后,所有的 Python 容器都不承諾線程安全,你要多線程做這件事,本身就必須得加鎖,這也說明了業(yè)務(wù)代碼設(shè)計有問題的.
但由“遍歷中刪除特定元素”這種特例,得出“遍歷dict的時候,養(yǎng)成使用 for k in d.keys() 的習(xí)慣”,我覺得有必要糾正一下。在普通的遍歷中,應(yīng)該使用 for k in adict。
另外,對于“遍歷中刪除元素”這種需求,pythonic 的做法是 adict = {k, v for adict.iteritems() if v != 0} 或 alist = [i for i in alist if i != 0]
這個寫法讓我眼前一亮:怎么還有這個語法?
再仔細(xì)一看,他可能是這個意思:
#!/usr/bin/env python # -*- coding=utf-8 -*- a = {'a':1, 'b':0, 'c':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, 'b':0, 'c':1, 'd':0} b={} for k,v in a.items(): if v != 0: b.update({k:v}) adict = b del b print a
不知道對不對。
因為這個寫法一開始讓我猛然想到三元操作符,仔細(xì)一看才發(fā)現(xiàn)不是,以前Goolge到有個解決方案
val = float(raw_input("Age: ")) status = ("working","retired")[val>65] print "You should be",status val = float(raw_input("Age: ")) status = ("working","retired")[val>65] print "You should be",status
val>65是個邏輯表達式,返回0或者1,剛好作為前面那個元組的ID來取值,實在是太妙了。。。
不過在Google的資料里面還有一個版本
#V1 if X else V2 s = None a = "not null" if s == None else s print a #'not null'
后來發(fā)帖在華蟒用戶組(中文Python技術(shù)郵件列表)中提到后眾多大神解答如下:
>>> alist = [1,2,0,3,0,4,5] >>> alist = [i for i in alist if i != 0] >>> alist [1, 2, 3, 4, 5] >>> d = {'a':1, 'b':0, 'c':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 }
相關(guān)文章
詳解js文件通過python訪問數(shù)據(jù)庫方法
在本篇內(nèi)容里小編給大家分享了關(guān)于js文件通過python訪問數(shù)據(jù)庫方法和技巧,有需要的朋友們跟著學(xué)習(xí)參考下。2019-03-03Python?ArcPy實現(xiàn)批量計算多時相遙感影像的各項元平均值
這篇文章主要為大家詳細(xì)介紹了如何基于Python中ArcPy模塊,實現(xiàn)對大量長時間序列柵格遙感影像文件的每一個像元進行多時序平均值的求取,感興趣的可以了解一下2023-04-04Python利用前序和中序遍歷結(jié)果重建二叉樹的方法
這篇文章主要介紹了Python利用前序和中序遍歷結(jié)果重建二叉樹的方法,實例分析了Python二叉樹的定義與遍歷操作技巧,需要的朋友可以參考下2016-04-04Python列表切片操作實例探究(提取復(fù)制反轉(zhuǎn))
在Python中,列表切片是處理列表數(shù)據(jù)非常強大且靈活的方法,本文將全面探討Python中列表切片的多種用法,包括提取子列表、復(fù)制列表、反轉(zhuǎn)列表等操作,結(jié)合豐富的示例代碼進行詳細(xì)講解2024-01-01python3.7安裝matplotlib失敗問題的完美解決方法
由于學(xué)習(xí)需要安裝matplotlib庫,閱讀網(wǎng)上教程后一直出現(xiàn)各種各樣的錯誤,下面這篇文章主要給大家介紹了關(guān)于python3.7安裝matplotlib失敗問題的完美解決方法,需要的朋友可以參考下2022-07-07tensorflow:指定gpu 限制使用量百分比,設(shè)置最小使用量的實現(xiàn)
今天小編就為大家分享一篇tensorflow:指定gpu 限制使用量百分比,設(shè)置最小使用量的實現(xiàn),具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-02-02