제너레이터를 두 번 읽으면 빈 목록이 나오는 이유

이 카테고리 글 목록

전체글 보기

같은 제너레이터로 합계를 낸 뒤 목록을 만들면, 합계를 낼 때 이미 항목을 끝까지 읽어서 빈 목록이 나온다. 같은 값을 여러 번 쓸 작은 유한 자료라면 처음 읽을 때 리스트에 담는다. 원천을 다시 읽을 수 있다면 새 이터레이터를 얻는 방법도 있다.

합계는 맞는데 목록이 빈 경우

counts = (value for value in [2, 3, 5])
print(sum(counts))
print(iter(counts) is counts)
print(list(counts))
10
True
[]

가상의 수량 세 개가 처음부터 비어 있었던 것은 아니다. sum이 같은 이터레이터를 끝까지 진행했다. iter(counts)도 그 객체를 그대로 돌려주므로 list(counts)에 남은 항목이 없다. Python 용어집의 이터레이터 설명은 끝까지 읽은 상태를 소진이라고 부른다.

한 번 모아 쓰거나, 새로 읽기

def read_counts():
    yield 2
    yield 3
    yield 5

saved = list(read_counts())
print(sum(saved), list(saved))

print(sum(read_counts()), list(read_counts()))
10 [2, 3, 5]
10 [2, 3, 5]

첫 줄의 계산은 처음부터 값을 담아 둔 리스트를 두 번 읽는다. 리스트를 순회할 때마다 새 이터레이터를 얻는다. 둘째 줄의 계산은 read_counts()를 두 번 호출해 각각 새 제너레이터를 얻는다. Python 데이터 모델의 제너레이터 함수 설명에서 함수 호출과 순회의 관계를 확인할 수 있다.

같은 항목을 다시 써야 하고 메모리에 담을 수 있다면, 소진되기 전에 저장한다. 원천을 다시 열 수 있어도 그 사이에 데이터가 바뀌거나 읽기 비용과 부수효과가 반복될 수 있다. 크거나 끝이 없는 스트림은 필요한 결과를 한 번의 순회에서 함께 계산할 수 있는지 먼저 살펴본다.

두 코드 블록은 각각 독립 실행할 수 있다. CPython 3.14.3과 Windows 11에서 위 출력값을 확인했다.

이 카테고리의 다른 글

전체글 보기

“제너레이터를 두 번 읽으면 빈 목록이 나오는 이유”에 대한 1개의 생각

댓글 남기기