복붙노트

[PYTHON] Python dict를 반복하면서 수정

PYTHON

Python dict를 반복하면서 수정

우리가 파이썬 사전 d를 가지고 있다고 가정 해 봅시다. 우리는 그것을 다음과 같이 반복합니다 :

for k,v in d.iteritems():
    del d[f(k)] # remove some item
    d[g(k)] = v # add a new item

(f와 g는 단지 블랙 박스 변환 일 뿐이다.)

즉 iteritem을 사용하여 iterating하는 동안 d에 항목을 추가 / 제거하려고합니다.

잘 정의되어 있습니까? 답을 뒷받침 할만한 참고 문헌을 제공해 주시겠습니까?

(깨진 경우이를 수정하는 방법은 매우 분명하기 때문에 이후의 각도는 아닙니다.)

해결법

  1. ==============================

    1.Python 문서 페이지 (Python 2.7)에서 명시 적으로 언급 한 내용은

    Python 문서 페이지 (Python 2.7)에서 명시 적으로 언급 한 내용은

    Python 3에서도 마찬가지입니다.

    iter (d), d.iterkeys () 및 d.itervalues ​​()에 대해서도 동일하게 적용되며, k.v에 대해서는 d.items ()에서 말하는 것과 같습니다. ( for가 무엇을하는지 정확히 기억하고 있지만 구현이 iter (d)를 호출하면 놀라지 않을 것입니다.

  2. ==============================

    2.알렉스 Martelli이 여기에 무게.

    알렉스 Martelli이 여기에 무게.

    컨테이너를 반복하는 동안 컨테이너 (예 : dict)를 변경하는 것이 안전하지 않을 수 있습니다. 그래서 del d [f (k)]는 안전하지 않을 수 있습니다. 아시는 바와 같이 d.iteritems () (동일한 기본 컨테이너를 사용함) 대신 d.items ()를 사용하여 컨테이너의 독립 사본을 루프하는 것입니다.

    dict의 기존 색인에서 값을 수정하는 것이 좋지만 새 색인에 값을 삽입하는 것 (예 : d [g (k)] = v)은 작동하지 않을 수 있습니다.

  3. ==============================

    3.최소한 d.iteritems ()에서는 그렇게 할 수 없습니다. 나는 그것을 시험해 보았고 파이썬은 실패했다.

    최소한 d.iteritems ()에서는 그렇게 할 수 없습니다. 나는 그것을 시험해 보았고 파이썬은 실패했다.

    RuntimeError: dictionary changed size during iteration
    

    대신 d.items ()를 사용하면 작동합니다.

    파이썬 3에서 d.items ()는 파이썬 2의 d.iteritems ()와 같은 사전을 보는 것이다. 파이썬 3에서는 d.copy (). items ()를 사용한다. 이것은 유사하게 우리가 반복하는 데이터 구조를 수정하지 않기 위해 사전 복사본을 반복 할 수있게 해줍니다.

  4. ==============================

    4.다음 코드는 이것이 잘 정의되어 있지 않음을 보여줍니다.

    다음 코드는 이것이 잘 정의되어 있지 않음을 보여줍니다.

    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)를 호출하고 예외를 throw합니다 (반복 중에 사전 크기가 변경됨).

    두 번째 예제는 h (k)를 호출하고 예외를 throw하지 않지만 다음을 출력합니다.

    {21: 'axx', 22: 'bxx', 23: 'cxx'}
    

    어떤 코드를 보면서, 잘못된 것 같습니다 - 나는 다음과 같은 것을 기대했을 것입니다 :

    {11: 'ax', 12: 'bx', 13: 'cx'}
    
  5. ==============================

    5.Numpy 배열을 포함하는 대형 사전이 있으므로 @ murgatroid99에서 제안한 dict.copy (). keys ()는 실현 가능하지 않았습니다. 대신, keys_view를 목록으로 변환하고 파이썬 3.4에서 잘 돌아갔다.

    Numpy 배열을 포함하는 대형 사전이 있으므로 @ murgatroid99에서 제안한 dict.copy (). keys ()는 실현 가능하지 않았습니다. 대신, keys_view를 목록으로 변환하고 파이썬 3.4에서 잘 돌아갔다.

    for item in list(dict_d.keys()):
        temp = dict_d.pop(item)
        dict_d['some_key'] = 1  # Some value
    

    위의 답변과 같이 파이썬의 내부 동작에 대한 철학적 영역에 뛰어 들지는 않지만 실현 된 해결책을 제시합니다.

  6. ==============================

    6.나는 동일한 문제를 겪었고이 문제를 해결하기 위해 다음 절차를 사용했습니다.

    나는 동일한 문제를 겪었고이 문제를 해결하기 위해 다음 절차를 사용했습니다.

    Python List는 iterating 중에 수정할 수 있습니다. 그래서 다음 코드에서는 1을 무한히 인쇄합니다.

    for i in list:
       list.append(1)
       print 1
    

    목록과 사전을 공동으로 사용하면이 문제를 해결할 수 있습니다.

    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))
    
  7. from https://stackoverflow.com/questions/6777485/modifying-a-python-dict-while-iterating-over-it by cc-by-sa and MIT license