파이썬(Python)은 딕셔너리(dictionary)의 키(key)로 무엇을 사용할 수 있는지에 대해 엄격한 규칙을 가지고 있습니다. 파이썬 딕셔너리에서 모든 키는 반드시 해시 가능(hashable)해야 합니다.
딕셔너리에 키를 추가할 때 해시 불가능한(unhashable) 타입을 키로 사용하려고 하면 "TypeError: unhashable type: 'dict'" 오류가 발생합니다.
이 글에서는 이 오류의 의미와 발생 원인을 살펴보고, 실제 예제를 통해 코드에서 이 오류를 해결하는 방법까지 단계별로 알아보겠습니다.
TypeError: unhashable type: 'dict' 오류란?
딕셔너리는 키(keys)와 값(values), 두 부분으로 구성됩니다. 키는 값에 연결된 식별자 역할을 하며, 특정 키를 참조하면 그 키와 연관된 값을 조회할 수 있습니다.
딕셔너리의 키로 사용할 수 있는 것은 오직 해시 가능한 객체뿐입니다. 문자열(string), 정수(integer), 튜플(tuple), 프로즌셋(frozenset)과 같은 불변(immutable) 객체는 일부 예외를 제외하고 해시 가능합니다. 따라서 딕셔너리 자체는 다른 딕셔너리의 키로 사용할 수 없습니다.
딕셔너리에 항목을 추가하려면 유효한 해시 가능한 키를 지정해야 합니다. 예를 들어 "name"은 유효한 키이지만, { "name": "test" }와 같은 딕셔너리 객체는 유효한 키가 아닙니다.
오류 발생 예제 시나리오
여기서는 베이커리에서 5번 이상 판매된 케이크 정보를 한 딕셔너리에서 다른 딕셔너리로 옮기는 프로그램을 작성해 보겠습니다.
먼저 각 케이크에 대한 정보를 담고 있는 딕셔너리들로 구성된 리스트를 선언합니다. 그리고 5번 이상 판매된 케이크를 저장할 딕셔너리도 함께 정의합니다.
cakes = [
{
"name": "Black Forest Gateau", "sold": 3
},
{
"name": "Carrot Cake", "sold": 7
},
{
"name": "Coconut and Lime Cake", "sold": 9
}
]
sold_more_than_five = {}
"cakes" 리스트에는 세 개의 딕셔너리가 들어 있으며, 각 딕셔너리는 두 개의 키와 값으로 구성되어 있습니다. 키 이름은 각각 "name"과 "sold"입니다.
이제 for 루프를 작성하여 케이크 목록을 순회하면서 5번 이상 판매된 케이크를 찾아 보겠습니다. 조건에 맞는 케이크는 "sold_more_than_five" 딕셔너리에 추가됩니다.
for c in cakes: if c["sold"] > 5: sold_more_than_five[c] = c["sold"] print(c["name"] + " has been sold more than five times.") print(sold_more_than_five)
for 루프 안에서는 각 딕셔너리의 "sold" 값이 5보다 큰지 비교합니다. 조건을 만족하면 해당 항목이 "sold_more_than_five" 딕셔너리에 추가되고, 해당 케이크가 5번 이상 판매되었다는 메시지가 콘솔에 출력됩니다.
루프 실행이 끝나면 "sold_more_than_five" 딕셔너리를 콘솔에 출력하도록 되어 있습니다. 그럼 코드를 실행해 프로그램이 제대로 작동하는지 확인해 보겠습니다.
Traceback (most recent call last): File "main.py", line 16, in <module> sold_more_than_five[c] = c["sold"] TypeError: unhashable type: 'dict'
실행 결과 오류가 발생했습니다. 원인을 살펴보겠습니다.
해결 방법
이 코드가 작동하지 않는 이유는, 딕셔너리를 사용해 또 다른 딕셔너리의 키를 만들려고 했기 때문입니다.
변수 "c"의 값은 "cakes" 리스트에 있는 딕셔너리 하나입니다. 즉, "sold_more_than_five" 딕셔너리에 항목을 추가하려는 순간, 우리는 실수로 딕셔너리 자체를 키로 추가하려 하고 있는 것입니다.
sold_more_than_five[c] = c["sold"]
"if" 문이 "Carrot Cake" 항목에 대해 실행될 때, 코드는 실질적으로 아래와 같이 동작하려 합니다.
sold_more_than_five[{"name": "Carrot Cake", "sold": 7}] = 7
이는 유효하지 않은 코드입니다. 딕셔너리를 다른 딕셔너리의 키로 추가하려 하기 때문입니다. 이 문제는 딕셔너리 전체가 아니라 c["name"]을 키로 사용하도록 수정하면 해결할 수 있습니다.
sold_more_than_five[c["name"]] = c["sold"]
수정된 코드로 다시 실행해 보겠습니다.
Carrot Cake has been sold more than five times.
Coconut and Lime Cake has been sold more than five times.
{'Carrot Cake': 7, 'Coconut and Lime Cake': 9}
이제 코드가 성공적으로 실행됩니다. 딕셔너리 대신 각 케이크의 이름을 키로 사용하도록 변경했기 때문입니다.
마무리
"TypeError: unhashable type: 'dict'" 오류는 딕셔너리에 새 항목을 추가할 때 해시 불가능한(unhashable) 객체를 키로 사용하려 할 때 발생합니다. 문자열, 튜플, 정수처럼 불변(immutable)인 객체만 딕셔너리의 키로 사용할 수 있다는 점을 기억하세요.
이 오류를 해결하려면 딕셔너리에 항목을 추가할 때 반드시 해시 가능한(hashable) 객체만 키로 사용해야 합니다. 이제 여러분도 전문 개발자처럼 이 흔한 파이썬 오류를 손쉽게 해결할 준비가 되었습니다!