Computer >> 컴퓨터 >  >> 프로그래밍 >> Python

Python TypeError: unhashable type: 'list' 오류 원인과 해결 방법

파이썬 딕셔너리(dictionary)는 키(key)로 해시 가능(hashable)한 데이터 타입만 허용합니다. 리스트(list)는 해시 가능한 타입이 아니기 때문에, 리스트를 딕셔너리의 키로 지정하면 "TypeError: unhashable type: 'list'" 오류가 발생합니다.

이 글에서는 이 오류가 의미하는 바와 코드에서 발생하는 이유를 설명하고, 실제 예제를 통해 해결 방법까지 단계별로 알아보겠습니다.

TypeError: unhashable type: 'list'란?

딕셔너리는 키(keys)값(values), 두 부분으로 구성됩니다. 키는 특정 값과 연결된 레이블 역할을 하며, 값을 조회하려면 반드시 해당 값의 키 이름을 참조해야 합니다.

값은 리스트부터 문자열까지 어떤 데이터 타입이든 자유롭게 사용할 수 있지만, 키로 사용할 수 있는 것은 해시 가능한 객체뿐입니다. 해시 가능한 객체란 시간이 지나도 해시 값이 변하지 않는 객체를 의미하며, 대표적인 예로 튜플(tuple)문자열(string)이 있습니다.

반면 리스트는 고정된 해시 값을 가지지 않습니다. 리스트의 내용이 바뀌면 해시 값도 함께 변경될 수 있기 때문에, 리스트를 딕셔너리의 키로 지정하는 것은 불가능합니다.

오류 발생 예제

평균 성적이 75점을 초과하는 학생들의 목록을 만드는 프로그램을 작성해 보겠습니다. 이 목록에는 각 학생의 이름과 성적 정보가 담긴 딕셔너리 레코드가 포함되며, 학교 전체 학생 명단과 성적이 저장된 데이터를 기준으로 필터링합니다.

먼저 학생 리스트와 우수 학생 정보를 담을 빈 딕셔너리를 정의합니다:

students = [
	{ "name": "Linda", "grades": [84, 82, 65] },
	{ "name": "Alex", "grades": [67, 68, 83] },
	{ "name": "Holly", "grades": [72, 74, 81] }
]
top_students = {}

"students" 리스트의 각 요소는 딕셔너리이며, 각 딕셔너리에는 name(이름)과 grades(성적)라는 두 개의 키가 있습니다. 또한 우수 학생 정보를 담을 "top_students"라는 빈 딕셔너리를 선언했습니다.

이제 for 반복문을 사용해 평균 성적이 75점을 넘는 학생만 골라 새 딕셔너리에 추가합니다:

for s in students:
	 average = sum(s["grades"]) / len(s["grades"])
	 if average > 75:
	         top_students[s["grades"]] = s["name"]

각 반복마다 학생의 모든 성적을 합산한 뒤 성적 개수로 나누어 평균을 계산합니다.

그다음 평균이 75보다 큰지 확인하고, 조건을 충족하면 top_students 딕셔너리에 새 항목을 생성합니다.

마지막으로 top_students 딕셔너리를 콘솔에 출력해 평균 성적이 75점을 넘는 모든 학생을 확인합니다:

print(top_students)

코드를 실행하면 어떻게 되는지 살펴보겠습니다:

Traceback (most recent call last):
  File "main.py", line 11, in <module>
	top_students[s["grades"]] = s["name"]
TypeError: unhashable type: 'list'

코드가 정상적으로 실행되지 않고 오류가 발생했습니다.

해결 방법

인터프리터가 11번째 줄에 도달하기 전까지 코드는 문제없이 동작합니다. 오류를 일으킨 코드는 다음과 같습니다:

top_students[s["grades"]] = s["name"]

오류의 원인은 리스트를 딕셔너리의 키로 사용하려 했기 때문입니다. 첫 번째 반복에서 이 코드는 다음과 같은 키와 값을 가진 딕셔너리를 만들려고 시도합니다:

{ [84, 82, 65]: "Linda" }

이것은 유효하지 않은 딕셔너리 구조입니다. 리스트는 키로 할당할 수 없기 때문에 코드가 실패하는 것입니다.

이 문제를 해결하려면 성적 리스트 대신 학생 이름을 키로 사용하고, 성적 리스트는 값으로 할당해야 합니다:

top_students[s["name"]] = s["grades"]

학생 이름이 키가 되고 성적 리스트가 값이 되도록 수정했습니다. 코드를 다시 실행해 보겠습니다:

{'Linda': [84, 82, 65], 'Holly': [72, 74, 81]}

이제 코드가 성공적으로 우수 학생 정보를 담은 딕셔너리를 생성했습니다. 최근 세 번의 시험에서 평균 성적이 75점을 초과한 학생들이 모두 딕셔너리에 추가되었습니다.

결과 딕셔너리의 구조는 다음과 같습니다:

  • 키(Keys): Linda, Holly
  • 값(Values): [84, 82, 65], [72, 74, 81]

이제 문자열을 키 이름으로 사용하기 때문에 코드가 정상적으로 작동합니다.

마무리

"TypeError: unhashable type: 'list'" 오류는 리스트를 딕셔너리의 키로 할당하려 할 때 발생합니다. 이 오류를 해결하려면 문자열이나 튜플처럼 해시 가능한 객체만 딕셔너리의 키로 사용해야 한다는 점을 기억하세요.

참고로 리스트를 꼭 키처럼 활용해야 하는 상황이라면, 리스트를 튜플(tuple)로 변환하거나 JSON 직렬화 후 문자열로 변환하는 방법도 유용하게 사용할 수 있습니다.

이제 여러분도 전문 개발자처럼 이 오류를 손쉽게 해결할 수 있습니다!