ホームページ >バックエンド開発 >Python チュートリアル >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, 'b':0, 'c':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, '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, 'b':0, 'c':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} #结果也是对的 >>>
実際、この問題はもともと非常に単純です。つまり、辞書が走査されるが、途中で変更される場合です。要素の追加や削除などのトラバーサルを実行すると、トラバーサルが終了し、反復中にディクショナリ サイズが変更されたという例外がスローされます。解決策は、ディクショナリ キー値をトラバースし、そのディクショナリ キー値に基づいてトラバースすることです。値はトラバーサルの継続には影響しません。
しかし、ここに別の優れた専門家が高い意見を述べています:
さらに、「トラバーサル中に要素を削除する」という要件については、Python のアプローチは adict = {k, v for adict.iteritems() if v != 0} または alist = [i for i in alist if i != 0 ]
よく見ると、彼は次のようなことを言っているのかもしれません:
#!/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それが正しいかどうかはわかりません。
この書き方をすると最初は三項演算子を思い出したので、詳しく見てみると、そうではないことがわかりました
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",statusval>65 は論理式です。 、0または1を返すのでちょうどいいです。前のタプルのIDとして使用できるのは非常に優れています。 。 。
しかし、Googleの情報には別のバージョンがあります
#V1 if X else V2 s = None a = "not null" if s == None else s print a #'not null'その後、Huanangユーザーグループ(中国のPython技術メーリングリスト)で言及され、多くの専門家が次のように答えました:
>>> 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'}If Python>=2.7 より大きい
次の記述方法も使用できます:
>>> d = {k:v for k,v in d.iteritems() if v !=0 }