반복하는 동안 Python dict 수정
Python 사전 d
이 있고이를 다음과 같이 반복 한다고 가정 해 보겠습니다 .
for k,v in d.iteritems():
del d[f(k)] # remove some item
d[g(k)] = v # add a new item
( f
그리고 g
일부 블랙 박스 변환입니다.)
즉,을 d
사용하여 반복 하는 동안 항목을 추가 / 제거하려고합니다 iteritems
.
잘 정의되어 있습니까? 답변을 뒷받침 할 참고 자료를 제공해 주시겠습니까?
(깨진 경우이를 고치는 방법은 매우 분명하므로 이것이 내가 추구하는 각도가 아닙니다.)
Python 문서 페이지 ( Python 2.7 용 ) 에 명시 적으로 언급되어 있습니다.
iteritems()
사전에 항목을 추가하거나 삭제하는 동안 사용하면 a가 발생RuntimeError
하거나 모든 항목을 반복하지 못할 수 있습니다.
Python 3과 유사합니다 .
동일에 대한 보유 iter(d)
, d.iterkeys()
그리고 d.itervalues()
, 나는 그것을 위해하는 것이 말까지 갈거야 for k, v in d.items():
(내가 정확히 기억하지 못하는 for
구현 호출하면 않지만, 나는 놀라지 않을 것이다 iter(d)
).
Alex Martelli는 여기 에서 이것에 무게를 둡니다 .
컨테이너를 반복하는 동안 컨테이너 (예 : dict)를 변경하는 것은 안전하지 않을 수 있습니다. 따라서 del d[f(k)]
안전하지 않을 수 있습니다. 아시다시피, 해결 방법은 d.items()
( d.iteritems()
동일한 기본 컨테이너를 사용하는 ) 대신 ( 컨테이너의 독립적 인 복사본을 반복 하기 위해 ) 사용하는 것입니다.
dict 의 기존 인덱스 에서 값을 수정하는 것은 괜찮지 만 새 인덱스 (예 :)에 값을 삽입하면 d[g(k)]=v
작동하지 않을 수 있습니다.
적어도 d.iteritems()
. 나는 그것을 시도했지만 Python은 실패합니다.
RuntimeError: dictionary changed size during iteration
대신을 사용 d.items()
하면 작동합니다.
Python 3에서는 Python 2 d.items()
와 같이 사전에 대한보기 d.iteritems()
입니다. Python 3에서이 작업을 수행하려면 대신 d.copy().items()
. 이것은 우리가 반복하는 데이터 구조를 수정하는 것을 피하기 위해 딕셔너리의 사본을 반복 할 수있게합니다.
다음 코드는 이것이 잘 정의되지 않았 음을 보여줍니다.
def f(x):
return x
def g(x):
return x+1
def h(x):
return x+10
try:
d = {1:"a", 2:"b", 3:"c"}
for k, v in d.iteritems():
del d[f(k)]
d[g(k)] = v+"x"
print d
except Exception as e:
print "Exception:", e
try:
d = {1:"a", 2:"b", 3:"c"}
for k, v in d.iteritems():
del d[f(k)]
d[h(k)] = v+"x"
print d
except Exception as e:
print "Exception:", e
첫 번째 예제는 g (k)를 호출하고 예외를 발생시킵니다 (반복 중에 사전 변경된 크기).
두 번째 예제는 h (k)를 호출하고 예외를 발생시키지 않지만 다음을 출력합니다.
{21: 'axx', 22: 'bxx', 23: 'cxx'}
코드를 보면 잘못된 것 같습니다. 다음과 같은 것을 예상했을 것입니다.
{11: 'ax', 12: 'bx', 13: 'cx'}
I have a large dictionary containing Numpy arrays, so the dict.copy().keys() thing suggested by @murgatroid99 was not feasible (though it worked). Instead, I just converted the keys_view to a list and it worked fine (in Python 3.4):
for item in list(dict_d.keys()):
temp = dict_d.pop(item)
dict_d['some_key'] = 1 # Some value
I realize this doesn't dive into the philosophical realm of Python's inner workings like the answers above, but it does provide a practical solution to the stated problem.
I got the same problem and I used following procedure to solve this issue.
Python List can be iterate even if you modify during iterating over it. so for following code it will print 1's infinitely.
for i in list:
list.append(1)
print 1
So using list and dict collaboratively you can solve this problem.
d_list=[]
d_dict = {}
for k in d_list:
if d_dict[k] is not -1:
d_dict[f(k)] = -1 # rather than deleting it mark it with -1 or other value to specify that it will be not considered further(deleted)
d_dict[g(k)] = v # add a new item
d_list.append(g(k))
Today I had a similar use-case, but instead of simply materializing the keys on the dictionary at the beginning of the loop, I wanted changes to the dict to affect the iteration of the dict, which was an ordered dict.
I ended up building the following routine, which can also be found in jaraco.itertools:
def _mutable_iter(dict):
"""
Iterate over items in the dict, yielding the first one, but allowing
it to be mutated during the process.
>>> d = dict(a=1)
>>> it = _mutable_iter(d)
>>> next(it)
('a', 1)
>>> d
{}
>>> d.update(b=2)
>>> list(it)
[('b', 2)]
"""
while dict:
prev_key = next(iter(dict))
yield prev_key, dict.pop(prev_key)
The docstring illustrates the usage. This function could be used in place of d.iteritems()
above to have the desired effect.
Python 3 you should just:
prefix = 'item_'
t = {'f1': 'ffw', 'f2': 'fca'}
t2 = dict()
for k,v in t.items():
t2[k] = prefix + v
or use:
t2 = t1.copy()
You should never modify original dictionary, it leads to confusion as well as potential bugs or RunTimeErrors. Unless you just append to the dictionary with new key names.
참고URL : https://stackoverflow.com/questions/6777485/modifying-a-python-dict-while-iterating-over-it
'programing' 카테고리의 다른 글
C ++ 가상 함수 반환 유형 (0) | 2020.10.24 |
---|---|
목록의 요소를 분할하는 방법은 무엇입니까? (0) | 2020.10.24 |
hg log-마지막 5 개의 로그 항목을 가져 오는 방법은 무엇입니까? (0) | 2020.10.24 |
특히 Node.js가 Apache보다 더 확장 가능한 이유는 무엇입니까? (0) | 2020.10.24 |
Entity Framework Fluent API를 사용하는 일대일 선택적 관계 (0) | 2020.10.24 |