Skip to content

2023-05-11 estsoft - python - inheritance, linked-list, method-overriding, MRO, private-member, iterator, generator, module, file-io, excel - https://realpython.com/introduction-to-python-generators/

Generator function generates iterator-like control block#

yield 문법이 나온다. yield 키워드를 가지고 있는 함수를 generator function이라고 부른다. 함수를 suspend 하고 generator 객체를 리턴하는 역할을 가지고 있다. 따라서 함수의 상태가 어딘가 저장이 되고 재호출이 되기를 기다린다. 해당 함수가 외부에서 다시 호출이 되면 yield 이후 문장들을 다시 실행하기 시작한다.

yield를 사용하여 리턴한 yield 객체로부터 데이터 뽑아내려면 next 내장 함수를 사용하자. 완전 이터레이터와 사용방법이 동일하지?

def my_yield():
    print('<my_yield> before yield')
    yield 1
    print('<my_yield> after yielding 1')
    yield 2
    print('<my_yield> after yielding 2')
    yield 3
    print('<my_yield> after yielding 3')

generated = my_yield()
print(next(generated))  # 1
print(next(generated))  # 2
print(next(generated))  # 3
print(next(generated))  # raise StopIteration

my_yield 함수에 대한 호출은 마치 리스트로부터 iter를 호출한 것 마냥 새로운 제너레이터 객체를 리턴하는 것 같다. 그래서 멍청하게 my_yield를 여러 번 호출했다가 잠깐 멘붕에 빠졌다.

print(next(my_yield()))  # 1 
print(next(my_yield()))  # 1 
print(next(my_yield()))  # 1 
print(next(my_yield()))  # 1 
print(next(my_yield()))  # 1 
print(next(my_yield()))  # 1 
...

나중에 멀티스레딩과 네트워크 프로그래밍과 함께 하면 복잡하게 얽혀 고오급 프로그래머가 될 수 있다.

아래 코드는 무한루프에 걸린다.

def gen():
    count = 0
    while True:
        yield count
        count += 1

for i in gen():
    print(i)

아래 코드는 무한한 짝수 정수를 게으르게 다루는 법에 대한 스니펫이다. gen()은 분명히 무한하지만 zip과 함께 사용하여 바운딩이 된다!

def gen():
    count = 0
    while True:
        yield count
        count += 2


l = [10, 20, 30, 40, 50]
print(list(zip(l, gen())))

type hint cheatsheet에 따르면, 제너레이터 함수의 리턴값은 그냥 Iterator라고 한다.

# A generator function that yields ints is secretly just a function that
# returns an iterator of ints, so that's how we annotate it
def gen(n: int) -> Iterator[int]:
    i = 0
    while i < n:
        yield i
        i += 1