- 제너레이터(Generator)는 이터레이터(iterator)를 생성해주는 함수입니다.
- 이터레이터는 클래스에
__iter__, __next__ 또는 __getitem__
메서드를 구현해야 하지만 제너레이터는 함수 안에서 yield라는 키워드만 사용하면 끝입니다.- 제너레이터는 이터레이터보다 훨씬 간단하게 작성할 수 있습니다.
- 제너레이터는는 발생자라고 부르기도 한다.
함수 안에서 yield를 사용하면 함수는 제너레이터가 되며 yield에는 값(변수)을 지정합니다.
yield는 함수가 제너레이터를 반환한다는 것을 제외하고 return과 비슷하게 사용되는 키워드입니다.
def number_generator(): yield 0 yield 1 yield 2 for i in number_generator(): print(i) # 0 # 1 # 2
__next__
메소드 안에서 직접 return으로 값을 반환했지만, 제너레이터는 yield에 지정한 값이 __next__
메소드의 반환값으로 나온다.__next__
메소드를 호출할 때마다 함수 안의 yield까지 코드를 실행하며 yield에서 값을 발생시킨다.def number_generator(): yield 0 # 0을 함수 바깥으로 전달하면서 코드 실행을 함수 바깥에 양보 yield 1 # 1을 함수 바깥으로 전달하면서 코드 실행을 함수 바깥에 양보 yield 2 # 2을 함수 바깥으로 전달하면서 코드 실행을 함수 바깥에 양보 g = number_generator() - print(g) # <generator object number_generator at 0x7fa66f973190> print(dir(g)) # ['__class__', '__del__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__iter__', '__le__', '__lt__', '__name__', '__ne__', '__new__', '__next__', '__qualname__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'close', 'gi_code', 'gi_frame', 'gi_running', 'gi_yieldfrom', 'send', 'throw'] - print(g.__next__()) # 0 print(g.__next__()) # 1 print(g.__next__()) # 2 print(g.__next__()) # StopIteration
즉, return은 반환 즉시 함수가 끝나지만 yield는 잠시 함수 바깥의 코드가 실행되도록 양보하여 값을 가져가게 한 뒤 다시 제너레이터 안의 코드를 계속 실행하는 방식입니다.
def number_generator(): yield 0 # 0을 함수 바깥으로 전달하면서 코드 실행을 함수 바깥에 양보 yield 1 # 1을 함수 바깥으로 전달하면서 코드 실행을 함수 바깥에 양보 yield 2 # 2을 함수 바깥으로 전달하면서 코드 실행을 함수 바깥에 양보 g = number_generator() - a = next(g) #yield를 사용하여 함수 바깥으로 전달한 값은 next의 반환값으로 나온다. b = next(g) c = next(g) print(a, b, c) # 0 1 2