노트

이터레이터와 제너레이터

Iterators and Generators

CS#python · 연결된 개념 4개

쉽게 말하면

이터레이터와 제너레이터는 물을 통째로 받아 둔 물통이 아니라, 틀 때마다 한 잔씩 나오는 수도꼭지예요. 값을 필요할 때 하나씩 만들어서, 큰 파일도 전부 메모리에 올리지 않고 처리할 수 있어요.

비유가 깨지는 곳 수도꼭지는 계속 나오지만 이터레이터는 한 번 다 쓰면 끝이에요. 다시 돌거나 길이·인덱스가 필요하면 리스트로 만들어요. yield는 지역 변수와 위치를 남긴 채 함수를 일시 정지해요.

이터레이터(iterator)는 __next__()로 값을 하나씩 내주다가 끝나면 StopIteration을 던지는 객체다. 제너레이터(generator)는 yield를 쓴 함수로, 이터레이터를 클래스 없이 간단히 만드는 방법이다. 둘 다 값을 필요할 때 하나씩 만들어(지연 평가, lazy evaluation) 메모리를 아낀다.

for문이 하는 일

for x in items:
    print(x)
 
# 실제로는
it = iter(items)          # items.__iter__() → 이터레이터
while True:
    try:
        x = next(it)      # it.__next__()
    except StopIteration:
        break
    print(x)
  • __iter__()를 가진 객체가 이터러블(iterable)(리스트, 딕셔너리, range, 파일), 그것이 돌려주는 __next__()를 가진 객체가 이터레이터다
  • 이터레이터는 한 번 다 쓰면 끝이다. 리스트는 매번 새 이터레이터를 만들어 여러 번 돌 수 있다

제너레이터

def read_lines(path):
    with open(path) as f:
        for line in f:
            if line.strip():
                yield line.rstrip()     # 여기서 멈췄다가 다음 next()에 이어서
 
for line in read_lines("big.log"):     # 파일 전체를 메모리에 올리지 않음
    ...
 
squares = (n * n for n in range(10**9))  # 제너레이터 표현식: 아직 아무것도 계산 안 함
  • yield는 return과 달리 함수를 끝내지 않고 일시 정지한다. 지역 변수와 실행 위치가 그대로 남는다
  • 무한 수열, 큰 파일·스트리밍 데이터 처리, 파이프라인 구성에 좋다
  • yield from 다른이터러블로 하위 제너레이터에 위임한다
  • 비동기 코루틴(coroutine, async def)도 이 "멈췄다 이어 가는 함수" 아이디어에서 나왔다(asyncio 태스크 예외가 조용히 사라지는 문제)

언제 쓰나

결과를 한 번만 순서대로 쓰고 버릴 거라면 리스트 대신 제너레이터가 낫다. 여러 번 쓰거나 길이·인덱스가 필요하면 리스트로 만든다. 반복을 변환 단계의 연결로 쓰는 습관은 반복문을 파이프라인으로 바꾸기과 같고, 자바스크립트의 이터레이터 프로토콜·제너레이터와도 거의 같은 모양이다. 지연 계산이 필요한 다른 예는 이벤트 루프의 비동기 처리에서 볼 수 있다.

출처: Python 용어집: iterator · generator · Python 튜토리얼: Iterators · Generators

연결된 개념

이 노트를 가리키는 문서

뜻이 가까운 노트

  • 파이썬 데코레이터

    파이썬 데코레이터는 함수(또는 클래스)를 받아 다른 호출 가능한 객체를 돌려주는 함수다. @deco를 함수 정의 위에 쓰면 func = deco(func)와 같다. 원래 함수 앞뒤에 로깅·권한 검사·캐시 같은 기능을 덧붙일 때 쓴다.

  • 데코레이터 패턴

    같은 인터페이스를 구현한 래퍼로 객체를 감싸, 원래 객체를 고치지 않고 앞뒤에 기능을 덧붙이는 패턴. 래퍼를 여러 겹 쌓아 기능을 조합할 수 있다.

  • 파이썬 클래스 기초

    파이썬 클래스는 데이터 속성(attribute)과 메서드를 묶은 타입이고, 클래스를 호출해 인스턴스(instance)를 만든다. 메서드의 첫 매개변수 self가 호출한 인스턴스 자신이며, 호출할 때는 파이썬이 자동으로 채워 넘긴다.

  • 읽기 전용 복제본

    읽기 전용 복제본은 주 DB(primary, writer)의 데이터를 복제해 읽기 요청만 받는 DB 인스턴스다. 쓰기는 writer 한 곳에서 처리하고, 읽기를 여러 복제본으로 나눠 부하를 분산한다.

  • 인출 연습과 간격 반복

    다시 읽기보다 기억에서 꺼내 보는 연습을, 시간을 두고 나눠서 할 때 가장 오래 남는다.

보기 옵션