Python 강좌 / 이터레이터와 제너레이터로 데이터를 순서대로 처리하기
이터레이터는 다음 항목을 하나씩 제공하는 객체이고 제너레이터는 yield로 그런 동작을 작성하는 방법입니다. 필요한 시점에 값을 계산할 수 있지만 한 번 소비한 결과를 자동으로 처음부터 다시 읽을 수 있는 것은 아닙니다.
반복 가능 객체와 이터레이터
리스트는 반복 가능한 객체이며 iter(list)는 그 목록을 읽는 이터레이터를 만듭니다. next로 다음 항목을 요청하고 더 없으면 StopIteration이 발생합니다. for는 이 종료 신호를 처리해 반복을 끝냅니다.
관련 동작과 지원 조건은 이터레이터와 제너레이터로 데이터를 순서대로 처리하기 관련 공식 문서에서 확인할 수 있습니다.
yield가 들어 있는 함수를 호출하면 본문을 끝까지 실행하는 대신 제너레이터 객체를 만듭니다. 다음 값을 요청할 때 본문을 진행하고 yield 위치에서 상태를 보존하며 멈춥니다.
전체 예제와 실행 결과
별도의 실습 폴더에서 아래 파일을 UTF-8로 저장합니다. 가상환경을 선택한 터미널에서 python generators.py 명령으로 실행합니다. macOS·Ubuntu에서 가상환경을 사용하지 않는 경우 명령 이름을 python3으로 바꿉니다.
generators.py 파일의 전체 내용입니다.
def running_totals(amounts):
total = 0
for amount in amounts:
total += amount
yield total
values = running_totals([3500, 8000, 2500])
print(next(values))
print(list(values))
print(list(values))
print(list(running_totals([3500, 8000, 2500])))
예상 결과는 다음과 같습니다.
3500 [11500, 14000] [] [3500, 11500, 14000]
지연 계산과 메모리의 실제 범위
전체 누적 결과를 리스트로 미리 만들지 않고 요청할 때 생성하므로 결과 보관 메모리를 줄일 수 있습니다. 하지만 입력 자체가 이미 큰 리스트라면 그 입력 메모리는 여전히 필요합니다. list(generator)로 모두 모으면 결과도 메모리에 저장됩니다.
제너레이터 표현식은 (변환식 for 항목 in 모음) 형태입니다. 여러 번 읽어야 하는 작은 결과는 리스트로 저장하는 편이 단순할 수 있습니다. 지연 계산은 무조건 더 빠르다는 보장이 아니라 평가 시점과 보관 방식을 바꾸는 선택입니다.
소비 시점의 오류와 자원 수명
제너레이터 본문에서 나는 예외는 객체를 만든 시점이 아니라 값을 소비하는 도중 발생할 수 있습니다. 파일을 여는 제너레이터는 일부만 읽고 중단했을 때 파일이 언제 닫히는지까지 설계해야 합니다. with로 파일 수명을 관리하는 호출 구조를 검토하세요.
- next를 한 번 더 호출하면 남은 결과가 어떻게 바뀌는지 확인합니다.
- 입력을 빈 리스트로 바꾸어 처음 next에서 종료 신호가 발생하는지 확인합니다.
- 두 번 읽으려면 새 제너레이터를 만들거나 결과를 저장해야 함을 코드로 확인합니다.




