오류 수정Python - Dictionary Changed Size During Iteration

Isaac Tony 2023년1월30일
  1. 사전의 얕은 사본 만들기
  2. 사전 항목을 목록으로 캐스팅
  3. 빈 목록에 키 추가
오류 수정Python - Dictionary Changed Size During Iteration

이 런타임 오류는 반복 중에 사전 개체에서 새 항목을 제거, 수정 또는 추가할 때 발생합니다. 이 오류는 사전을 통해 반복할 때 발생하지만 사용된 프로그래밍 언어에 관계없이 거의 모든 반복 가능한 개체입니다.

아래 코드 스니펫은 사전을 반복하면서 동시에 변경을 수행할 때 이 오류가 어떻게 발생하는지 보여줍니다.

cars = {"brand": "Tesla", "model": "Model S Plaid", "year": 2021}

for x in cars.keys():
    cars["color"] = "white"
print(x)

위의 코드 블록에서 반복하는 동안 원래 사전에 새 항목을 추가합니다. 이것은 런타임 오류를 반환하여 반복 중에 사전 크기가 변경되었음을 알려주므로 동시에 반복하는 동안 사전을 수정할 수 없음을 의미합니다.

샘플 코드:

Traceback (most recent call last):
File "<string>", line 8, in <module>
RuntimeError: dictionary changed size during iteration

객체에 대한 반복을 수행하는 동안 삭제, 추가 또는 수정은 모두 변경으로 간주되며 반복하는 동안 수행할 수 없습니다. 아래 코드 예제는 반복하는 동안 사전을 수정하는 경우에도 이 오류가 지속된다는 것을 보여줍니다. 따라서 반복하는 동안 사전에서 기존 항목을 제거하면 여전히 동일한 오류가 발생합니다.

샘플 코드:

cars = {"brand": "Tesla", "model": "Model S Plaid", "year": 2021}

for x in cars.keys():
    del cars["model"]
print(cars)

출력:

Traceback (most recent call last):
File "<string>", line 8, in <module>
RuntimeError: dictionary changed size during iteration

Python 3에서 변경 객체를 반복하는 것은 잘못된 코드 작성 스타일로 간주되며 안전하지 않습니다. 일반적으로 프로그래밍에서는 객체를 동시에 반복하는 동안 객체를 변경할 수 없습니다. 이 규칙은 목록 및 배열과 같은 이터러블까지 확장됩니다.

그러나 함수가 개체를 변경하는 경우 함수가 원래 개체의 복사본만 변경하고 원래 개체는 그대로 유지하도록 해야 합니다. 이것은 객체를 동시에 반복하면서 객체를 변경하는 널리 사용되는 접근 방식 중 하나입니다.

이는 결국 메모리 고갈로 이어질 수 있는 무한 루프 생성을 방지하는 좋은 방법이자 가장 좋은 방법입니다. 이 오류를 처리하는 데 여러 솔루션을 사용할 수 있으며 여기에서 각각에 대해 설명합니다.

사전의 얕은 사본 만들기

Python은 원본 객체에 대한 바인딩 없이 객체의 복사본을 생성할 수 있는 copy() 모듈을 제공합니다. 이렇게 하면 원본 개체를 그대로 두고 개체의 복사본을 자유롭게 수정할 수 있습니다.

Python에서 할당 연산자를 사용하여 동일한 것을 실현할 수 없다는 점에 유의하십시오. 할당 연산자를 사용하면 원래 개체의 복사본이 생성되지 않고 오히려 원래 개체를 참조하는 변수가 생성됩니다.

따라서 새 개체에 대한 수정 사항은 원래 개체에도 영향을 미칩니다. 신규 개발자는 종종 이 연산자를 오용합니다.

샘플 코드:

import copy

cars = {
    "brand": "Tesla",
    "model": "Model S Plaid",
    "year": 2021,
}

# creating a shallow copy
cars_copy = copy.copy(cars)

for x in cars_copy.keys():
    cars["color"] = "black"

print(cars)
print(cars_copy)

출력:

{'brand': 'Tesla', 'model': 'Model S Plaid', 'year': 2021, 'color': 'black'}
{'brand': 'Tesla', 'model': 'Model S Plaid', 'year': 2021}

제공된 샘플 코드에서 복사 모듈의 copy 기능을 사용하여 원본 사전에 영향을 주지 않고 자유롭게 반복할 수 있는 사전 복사본을 만들었습니다. 사전 복사본을 변경하면 오류가 발생하지 않고 사전을 반복할 수 있습니다.

또는 두 개의 별표 연산자라고도 하는 ** 연산자를 사용하여 아래와 같이 위의 코드를 다시 작성할 수 있습니다.

샘플 코드:

cars = {"brand": "Tesla", "model": "Model S Plaid", "year": 2021}

# creating a shallow copy
cars_copy = {**cars}


for x in cars_copy.keys():
    cars["color"] = "black"

print(cars)

** 연산자는 한 사전에서 키-값 쌍을 가져와 다른 사전에 덤프할 수 있습니다.

연산자는 Python에서 키워드 인수를 전달하는 데 널리 사용되지만 사전 압축을 풀고 위의 코드에서 키-값 쌍을 얻기 위해 연산자를 사용했습니다. 그런 다음 사전의 복사본을 만들고 이 새 사전에 압축을 푼 값을 덤프합니다.

출력:

'brand': 'Tesla', 'model': 'Model S Plaid', 'year': 2021, 'color': 'black'}

사전에서 키-값 쌍을 삭제하는 것도 반복을 수행할 때 예외가 아니므로 유사한 접근 방식을 따라야 합니다. 따라서 동일한 절차를 사용하여 아래와 같이 model이라는 키와 해당 값 Model S Plaid를 삭제합니다.

샘플 코드:

import copy

cars = {"brand": "Tesla", "model": "Model S Plaid", "year": 2021, "color": "black"}

cars_copy = copy.copy(cars)

for x in cars_copy.keys():
    if x == "model":
        del cars["model"]

print(cars)

출력:

{'brand': 'Tesla', 'year': 2021, 'color': 'black'}

또 다른 솔루션은 사전을 수정하는 동안 반복할 수 있는 키 복사본을 만드는 것입니다. 그러나 이것은 Python 3에서 수행할 때 키가 iterable을 반환하지 않기 때문에 Python 2에서만 작동하고 Python 3에서는 작동하지 않습니다.

샘플 코드:

cars = {"brand": "Tesla", "model": "Model S Plaid", "year": 2021, "color": "black"}

key_copys = list(cars.keys())
print(key_copys)

for key in list(key_copys):
    if cars[key] == "model":
        cars.pop("model")

print(cars)

샘플 출력:

['brand', 'model', 'year', 'color']
{'brand': 'Tesla', 'model': 'Model S Plaid', 'year': 2021, 'color': 'black'}

사전 항목을 목록으로 캐스팅

변경하는 동안 사전을 반복할 수 없으므로 대신 캐스팅 목록을 만들고 사전을 변경하는 동안 목록을 반복할 수 있습니다. 원래 사전 대신 캐스팅 목록을 반복해도 런타임 오류가 반환되지 않습니다.

샘플 코드:

cars = {"brand": "Tesla", "model": "Model S Plaid", "year": 2021}

for i in list(cars):
    cars["color"] = "black"

print(cars)

출력:

{'brand': 'Tesla', 'model': 'Model S Plaid', 'year': 2021, 'color': 'black'}

빈 목록에 키 추가

반복하는 동안 사전을 변경하지 않으려면 반복을 수행하는 동안 사전 키가 포함된 빈 목록을 만들 수 있습니다. 이 빈 목록을 사용하여 제거하거나 변경하려는 모든 키를 추가한 다음 pop() 함수를 사용하여 키를 제거하거나 append 함수를 사용하여 새 키-값 쌍을 추가할 수 있습니다.

아래 코드와 같이 실행할 수 있습니다.

샘플 코드:

cars = {"brand": "Tesla", "model": "Model S Plaid", "year": 2021}

list = []

for i in cars:
    list.append(i)

for x in list:
    if x == "model":
        cars.pop(x)

print(cars)

출력:

{'brand': 'Tesla', 'year': 2021}

아래와 같이 for 루프를 사용하여 반복하면서 동일한 절차를 사용하여 사전에 새 키-값 쌍을 추가할 수 있습니다.

샘플 코드:

cars = {"brand": "Tesla", "model": "Model S Plaid", "year": 2021}

list = []

for i in cars:
    list.append(i)

for x in list:
    cars["color"] = "black"

print(cars)

출력:

{'brand': 'Tesla', 'model': 'Model S Plaid', 'year': 2021, 'color': 'black'}
작가: Isaac Tony
Isaac Tony avatar Isaac Tony avatar

Isaac Tony is a professional software developer and technical writer fascinated by Tech and productivity. He helps large technical organizations communicate their message clearly through writing.

LinkedIn

관련 문장 - Python Dictionary