Das Ändern von Elementen während des Wörterbuchdurchlaufs in Python führt zu Ausnahmen

高洛峰
Freigeben: 2017-03-02 16:49:24
Original
1066 Leute haben es durchsucht

Lassen Sie uns zunächst einige grundlegende Methoden zum Durchlaufen von Wörterbüchern in Python überprüfen:

Skript:

#!/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
Nach dem Login kopieren

Ausführungsergebnisse:

##########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
Nach dem Login kopieren

Nun, dann kommen wir zum „Hauptthema“--

Ein Absatz über Python Die „Debatte“ der Wörterbuchdurchquerung....
Auszug zuerst:

#这里初始化一个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
{&#39;a&#39;: 1, &#39;c&#39;: 1, &#39;d&#39;: 0}

>>> d = {&#39;a&#39;:1, &#39;b&#39;:0, &#39;c&#39;:1, &#39;d&#39;:0}
#d.keys() 是一个下标的数组
>>> d.keys()
[&#39;a&#39;, &#39;c&#39;, &#39;b&#39;, &#39;d&#39;]
#这样遍历,就没问题了,因为其实其实这里遍历的是d.keys()这个list常量。
>>> for k in d.keys():
...  if d[k] == 0:
...   del(d[k])
...
>>> d
{&#39;a&#39;: 1, &#39;c&#39;: 1}
#结果也是对的
>>>

#这里初始化一个dict
>>> d = {&#39;a&#39;:1, &#39;b&#39;:0, &#39;c&#39;:1, &#39;d&#39;: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
{&#39;a&#39;: 1, &#39;c&#39;: 1, &#39;d&#39;: 0}
 
>>> d = {&#39;a&#39;:1, &#39;b&#39;:0, &#39;c&#39;:1, &#39;d&#39;:0}
#d.keys() 是一个下标的数组
>>> d.keys()
[&#39;a&#39;, &#39;c&#39;, &#39;b&#39;, &#39;d&#39;]
#这样遍历,就没问题了,因为其实其实这里遍历的是d.keys()这个list常量。
>>> for k in d.keys():
...  if d[k] == 0:
...   del(d[k])
...
>>> d
{&#39;a&#39;: 1, &#39;c&#39;: 1}
#结果也是对的
>>>
Nach dem Login kopieren

Tatsächlich ist dieses Problem ist sehr einfach, das heißt, wenn ein Wörterbuch durchlaufen wird, es sich jedoch während des Durchlaufs ändert, z. B. durch Hinzufügen oder Löschen eines Elements, wird der Durchlauf beendet und eine Ausnahme der während der Iteration geänderten Größe des Wörterbuchs wird ausgelöst.
Die Die Lösung besteht darin, die Schlüsselwerte des Wörterbuchs zu durchlaufen und das Wörterbuch zu verwenden. Die Traversierung basiert auf dem Schlüsselwert, sodass eine Änderung des Werts keinen Einfluss auf die Fortsetzung der Traversierung hat.
Aber hier ist ein weiterer großartiger Experte, der eine hohe Meinung abgegeben hat:

Zunächst empfiehlt Python die Verwendung von Iteratoren, also für k in adict-Form. Zweitens wird das Löschen von Elementen im Container während des Durchlaufs in Bibliotheken wie C++ STL und Python nicht empfohlen, da diese Situation oft darauf hinweist, dass ein Problem mit Ihrem Entwurfsplan vorliegt und alle spezielle Anforderungen haben, die Python entsprechen adict.key(), um eine Kopie zu erstellen. Schließlich versprechen nicht alle Python-Container Thread-Sicherheit. Wenn Sie dies mit mehreren Threads tun möchten, müssen Sie diese sperren. Dies zeigt auch, dass ein Problem mit dem Geschäftscode-Design vorliegt „Durchquerung“ Im Sonderfall „Bestimmte Elemente löschen“ bin ich zu dem Schluss gekommen, dass „beim Durchlaufen von Diktat die Gewohnheit entwickelt wird, for k in d.keys () zu verwenden“, und ich denke, dass es notwendig ist, dies zu korrigieren. Bei der normalen Durchquerung sollten Sie for k in adict verwenden.

Darüber hinaus lautet der pythonische Ansatz für die Anforderung „Elemente während des Durchlaufens entfernen“ adict = {k, v für adict.iteritems() if v != 0} oder alist = [i for i in alist if i ! = 0]


Diese Schreibweise ließ meine Augen leuchten: Warum gibt es immer noch diese Syntax?

Bei genauem Hinsehen könnte er Folgendes meinen:


#!/usr/bin/env python
# -*- coding=utf-8 -*-
a = {&#39;a&#39;:1, &#39;b&#39;:0, &#39;c&#39;:1, &#39;d&#39;: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 = {&#39;a&#39;:1, &#39;b&#39;:0, &#39;c&#39;:1, &#39;d&#39;:0}
b={}
for k,v in a.items():
  if v != 0:
    b.update({k:v})
adict = b
del b
print a
Nach dem Login kopieren

Ich weiß nicht, ob das richtig ist.

Denn diese Schreibweise ließ mich zunächst an den ternären Operator denken. Bei genauerem Hinsehen wurde mir klar, dass es vorher keine Lösung gab


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
Nach dem Login kopieren

val>65 ist ein logischer Ausdruck, der 0 oder 1 zurückgibt, was zufällig die ID des vorherigen Tupels ist, was wirklich wunderbar ist. . .

Es gibt jedoch eine andere Version in den Google-Informationen


#V1 if X else V2
s = None
a = "not null" if s == None else s
print a
#&#39;not null&#39;
Nach dem Login kopieren

Später wurde sie in der Huanang-Benutzergruppe (chinesische technische Python-Mailingliste) veröffentlicht. Nach der Ankunft antworteten viele Experten wie folgt:


>>> alist = [1,2,0,3,0,4,5]
>>> alist = [i for i in alist if i != 0]
>>> alist

[1, 2, 3, 4, 5]

>>> d = {&#39;a&#39;:1, &#39;b&#39;:0, &#39;c&#39;:1, &#39;d&#39;:0}
>>> d = dict([(k,v) for k,v in d.iteritems() if v!=0])
>>> d
{&#39;a&#39;:1,&#39;c&#39;:1&#39;}
Nach dem Login kopieren

Wenn es größer als Python>=2,7

ist, können Sie es auch verwenden dieses Schreibens:


>>> d = {k:v for k,v in d.iteritems() if v !=0 }
Nach dem Login kopieren


Weitere verwandte Artikel über Ausnahmen, die durch das Ändern von Elementen während der Wörterbuchdurchquerung in Python verursacht werden, finden Sie bitte Achten Sie auf die chinesische PHP-Website!

Verwandte Etiketten:
Quelle:php.cn
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage
Über uns Haftungsausschluss Sitemap
Chinesische PHP-Website:Online-PHP-Schulung für das Gemeinwohl,Helfen Sie PHP-Lernenden, sich schnell weiterzuentwickeln!