Python 강좌 / 이터레이터와 제너레이터로 데이터를 순서대로 처리하기
이터레이터는 다음 항목을 하나씩 제공하는 객체이고 제너레이터는 yield로 그런 동작을 작성하는 방법입니다. 필요한 시점에 값을 계산할 수 있지만 한 번 소비한 결과를 자동으로 처음부터 다시 읽을 수 있는 것은 아닙니다.
반복 가능 객체와 이터레이터
리스트는 반복 가능한 객체이며 iter(list)는 그 목록을 읽는 이터레이터를 만듭니다. next로 다음 항목을 요청하고 더 없으면 StopIteration이 발생합니다. for는 이 종료 신호를 처리해 반복을 끝냅니다.
관련 동작과 지원 조건은 Python: classes에서 확인할 수 있습니다.
yield가 들어 있는 함수를 호출하면 본문을 끝까지 실행하는 대신 제너레이터 객체를 만듭니다. 다음 값을 요청할 때 본문을 진행하고 yield 위치에서 상태를 보존하며 멈춥니다.
파일 스트림과 연속 그룹 처리은 텍스트 파일 읽고 쓰기: with와 문자 인코딩 및 collections·itertools로 집계와 반복 처리하기에서 사용하는 규칙과 연결됩니다.
전체 예제와 실행 결과
별도의 실습 폴더에서 아래 파일을 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 모음) 형태입니다. 여러 번 읽어야 하는 작은 결과는 리스트로 저장하는 편이 단순할 수 있습니다. 지연 계산은 무조건 더 빠르다는 보장이 아니라 평가 시점과 보관 방식을 바꾸는 선택입니다.
list는 값을 보관하고, iter(list)는 그 값을 순서대로 꺼내는 현재 위치를 보관합니다. next를 한 번 호출한 뒤 list로 나머지를 모으면 이미 꺼낸 값은 다시 나오지 않습니다. 다 쓴 반복자를 다시 list로 감싸면 빈 목록이지만 원본 리스트는 남아 있습니다. 아래 제너레이터 표현식도 소비되며 값을 필요할 때 계산합니다.
아래 전체 코드를 iterator.py로 저장하고 같은 실습 폴더에서 python iterator.py로 실행합니다.
values = [1, 2, 3]
iterator = iter(values)
print(next(iterator))
print(list(iterator))
print(list(iterator))
print(list(values))
expression = (n * 2 for n in values)
print(list(expression))
예상 결과:
1
[2, 3]
[]
[1, 2, 3]
[2, 4, 6]
소비 시점의 오류와 자원 수명
제너레이터 본문에서 나는 예외는 객체를 만든 시점이 아니라 값을 소비하는 도중 발생할 수 있습니다. 파일을 여는 제너레이터는 일부만 읽고 중단했을 때 파일이 언제 닫히는지까지 설계해야 합니다. with로 파일 수명을 관리하는 호출 구조를 검토하세요.
- next를 한 번 더 호출하면 남은 결과가 어떻게 바뀌는지 확인합니다.
- 입력을 빈 리스트로 바꾸어 처음 next에서 종료 신호가 발생하는지 확인합니다.
- 두 번 읽으려면 새 제너레이터를 만들거나 결과를 저장해야 함을 코드로 확인합니다.




