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

Python TypeError: 'NoneType' object is not iterable 오류 해결 방법

Python에서는 값이 있는 객체만 반복(iterate)할 수 있습니다. 반복 가능한 객체는 값이 None이 아닐 때만 다음 항목에 접근할 수 있기 때문입니다. None 객체를 반복하려고 시도하면 TypeError: 'NoneType' object is not iterable 오류가 발생합니다.

이 글에서는 이 오류의 의미와 발생 원인을 살펴보고, 실제 예제를 통해 해결 방법을 단계별로 알아보겠습니다.

TypeError: 'NoneType' object is not iterable 오류란?

객체가 반복 가능하려면 반드시 값을 포함해야 합니다. None 값은 어떠한 객체도 담고 있지 않기 때문에 반복할 수 없으며, None은 null 값을 나타냅니다.

여기서 중요한 점은 None 객체와 비어 있는 반복 가능 객체(empty iterable)는 서로 다르다는 것입니다. 빈 리스트나 빈 문자열이 있을 때는 이 오류가 발생하지 않습니다.

리스트와 문자열은 반복 가능한 데이터 타입이기 때문입니다. Python 인터프리터는 빈 리스트를 만나면 반복할 값이 없다고 판단하여 그냥 넘어갑니다. 반면 None 값은 반복 자체가 불가능하므로 인터프리터가 오류를 반환합니다.

이 오류는 특히 함수를 선언한 후 return 문을 작성하는 것을 잊어버렸을 때 자주 발생합니다.

예제 시나리오

학생 이름 목록을 받아 "E"로 시작하는 이름만 걸러낸 뒤, 결과를 콘솔에 출력하는 프로그램을 작성해 보겠습니다.

먼저 학생 이름을 필터링하는 함수를 정의합니다:

def filter_students(class_names):
	new_class_names = []
	for c in class_names:
		if c.startswith("E"):
			new_class_names.append(c)

이 함수는 for 루프를 사용해 "class_names" 리스트의 모든 항목을 하나씩 확인합니다. 각 항목이 "E"로 시작하는지 검사하고, 조건에 맞으면 "new_class_names" 리스트에 추가합니다.

다음으로, 새 목록을 순회하며 각 값을 콘솔에 출력하는 함수를 작성합니다:

def show_students(class_names):
	for c in class_names:
		print(c)

이제 프로그램에서 사용할 학생 리스트를 선언하고, 이 리스트를 filter_students 함수에 전달합니다:

students = ["Elena", "Peter", "Chad", "Sam"]
students_e_name = filter_students(students)

이 코드는 filter_students 함수를 실행해 이름이 "E"로 시작하는 모든 학생을 찾고, 그 결과를 students_e_name 변수에 저장합니다. 이어서 show_students 함수를 호출해 새 학생 목록을 화면에 표시합니다:

show_students(students_e_name)

코드를 실행해 보겠습니다:

Traceback (most recent call last):
  File "main.py", line 14, in <module>
	show_students(students_e_name)
  File "main.py", line 8, in show_students
	for c in class_names:
TypeError: 'NoneType' object is not iterable

코드가 오류 메시지를 반환하며 중단됩니다.

해결 방법

show_students 함수 내에서 class_names 변수를 반복하려는 순간, 코드는 None 값을 감지하고 오류를 발생시킵니다. "class_names" 매개변수로 전달된 값이 None이기 때문입니다.

원인은 filter_students 함수가 아무 값도 반환하지 않는다는 데 있습니다. 함수의 실행 결과를 students_e_name 변수에 할당하는 시점에 None 값이 저장되는 것입니다.

이 오류를 해결하려면 filter_students 함수에 return 문을 추가해야 합니다:

def filter_students(class_names):
	new_class_names = []
	for c in class_names:
		if c.startswith("E"):
			new_class_names.append(c)
	# return 문을 추가했습니다
	return new_class_names

def show_students(class_names):
	for c in class_names:
		print(c)

students = ["Elena", "Peter", "Chad", "Sam"]
students_e_name = filter_students(students)

show_students(students_e_name)

이제 이 코드는 new_class_names의 값을 메인 프로그램으로 반환합니다.

다시 코드를 실행해 보겠습니다:

Elena

이제 코드가 "E"로 시작하는 이름을 가진 학생의 이름을 성공적으로 출력합니다.

NoneType 예외 미리 방지하기

엄밀히 말하면, 값을 반복하기 전에 해당 값이 None인지 먼저 검사하면 NoneType 예외 자체를 피할 수 있습니다. 다음 코드를 살펴보세요:

def filter_students(class_names):
	new_class_names = []
	for c in class_names:
		if c.startswith("E"):
			new_class_names.append(c)
	return new_class_names

def show_students(class_names):
	if class_names is not None:
		for c in class_names:
			print(c)

students = ["Elena", "Peter", "Chad", "Sam"]
students_e_name = filter_students(students)

show_students(students_e_name)

"show_students()" 함수는 class_names를 반복하기 전에 None 값인지 확인하기 때문에 정상적으로 실행됩니다. 하지만 대부분의 경우 이 방법이 모범 사례는 아닙니다. NoneType 오류의 진짜 원인이 코드의 다른 부분에 숨어 있을 수 있기 때문입니다.

예를 들어 전체 프로그램에 "is not None" 검사를 추가하면, 다른 함수에서 return 문을 누락했다는 사실 자체를 알아차리지 못하게 됩니다. 따라서 이 오류를 만났을 때는 "is not None" 검사로 감싸 처리하기보다, 근본 원인을 찾아 수정하는 것이 좋습니다.

마무리

TypeError: 'NoneType' object is not iterable 오류는 값이 None인 객체를 반복하려고 할 때 발생합니다.

이 오류를 해결하려면 반복하려는 모든 값에 문자열이나 리스트처럼 반복 가능한 객체가 제대로 할당되어 있는지 확인해야 합니다. 위 예제에서는 함수에 return 문을 추가하지 않아 함수가 리스트 대신 None을 반환했던 것이 원인이었습니다.

이제 여러분의 코드에서도 이 흔한 Python 오류를 자신 있게 해결할 수 있을 것입니다.