Heim >Backend-Entwicklung >Python-Tutorial >Das Ändern von Elementen während des Wörterbuchdurchlaufs in Python führt zu Ausnahmen

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

高洛峰
高洛峰Original
2017-03-02 16:49:241132Durchsuche

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

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

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}
#结果也是对的
>>>

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

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

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;

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;}

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 }


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!

Stellungnahme:
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