programing

반복하는 동안 Python dict 수정

nasanasas 2020. 10. 24. 10:21
반응형

반복하는 동안 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

반응형