>  기사  >  백엔드 개발  >  Python에서 사전 순회 중에 요소를 변경하면 예외가 발생합니다.

Python에서 사전 순회 중에 요소를 변경하면 예외가 발생합니다.

高洛峰
高洛峰원래의
2017-03-02 16:49:241067검색

먼저 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에 대한 단락 Dictionary traversal" Argument"....
발췌 첫 번째:

#这里初始化一个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}
#结果也是对的
>>>

사실 이 문제는 매우 간단합니다. 사전을 순회하지만 순회 중에 요소를 추가하거나 삭제하는 등 변경하면 순회가 종료되고 반복 중에 사전 크기가 변경되었다는 예외가 발생합니다.
해결책은 사전 키 값을 순회하는 것입니다. ​그리고 사전 키 값을 기준으로 순회합니다. 이러한 방식으로 값을 변경해도 순회 지속에는 영향을 미치지 않습니다.
그런데 높은 의견을 주신 또 다른 훌륭한 전문가가 있습니다.

우선 Python에서는 반복자 사용, 즉 adict 형식의 k를 사용할 것을 권장합니다. 둘째, 순회 중에 컨테이너의 요소를 삭제하는 것은 C++ STL 및 Python과 같은 라이브러리에서 권장되지 않습니다. 이러한 상황은 종종 디자인 계획에 문제가 있음을 나타내고 모두 Python에 해당하는 특별한 요구 사항이 있음을 나타내기 때문입니다. adict.key()를 사용하여 복사본을 만듭니다. 마지막으로, 모든 Python 컨테이너는 스레드 안전성을 보장하지 않습니다. 다중 스레드로 이를 수행하려면 이를 잠가야 합니다. 이는 비즈니스 코드 설계에 문제가 있음을 나타냅니다.

하지만 "순회" "특정 요소 삭제"라는 특수한 경우에는 "dict를 순회할 때 d.keys()에서 for k를 사용하는 습관을 길러라"라는 결론에 이르렀고, 이를 바로잡는 것이 필요하다고 생각합니다. 일반적인 순회에서는 adict에서 for k를 사용해야 합니다.
또한 "순회 중 요소 제거" 요구 사항에 대해 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 = {&#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
.

val>65는 0 또는 1을 반환하는 논리식인데, 이는 이전 튜플의 ID인데 정말 훌륭합니다. . .
그런데 구글의 정보에는 다른 버전이 있습니다

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

나중에 Huanang 사용자 그룹(중국 Python 기술 메일링 리스트)에 게시한 후, 언급한 많은 전문가들이 다음과 같이 답변했습니다.

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

Python>=2.7
보다 크면 다음과 같은 글을 써도 됩니다.

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


Python에서 사전 순회 중 요소 변경으로 인해 발생하는 예외에 대한 더 많은 관련 기사를 보려면 PHP에 주의하세요. 중국사이트!


성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.