이터레이터를 생성해주는 함수로 발생자라고도 한다. 이터레이터는 클래스에 iter, next 또는 getitem 메서드를 구현해야 하지만 제너레이터는 함수 안에서 yield라는 키워드만 사용해 간단하다.
함수 안에서 yield를 사용하면 함수는 제너레이터가 되며 yield에는 값(변수)을 지정한다.
yield 값
def number_generator():
yield 0
yield 1
yield 2
for i in number_generator():
print(i)
# 실행 결과
0
1
2
for 반복문 대신 next 함수로 __next__ 메서드를 직접 호출한다.
변수 = next(제너레이터객체)
def number_generator():
yield 0 # 0을 함수 바깥으로 전달하면서 코드 실행을 함수 바깥에 양보
yield 1 # 1을 함수 바깥으로 전달하면서 코드 실행을 함수 바깥에 양보
yield 2 # 2를 함수 바깥으로 전달하면서 코드 실행을 함수 바깥에 양보
g = number_generator()
a = next(g) # yield를 사용하여 함수 바깥으로 전달한 값은 next의 반환값으로 나옴
print(a) # 0
b = next(g)
print(b) # 1
c = next(g)
print(c) # 2
# 실행 결과
0
1
2
제너레이터는 함수를 끝내지 않은 상태에서 yield를 사용하여 값을 바깥으로 전달할 수 있다. 즉, return은 반환 즉시 함수가 끝나지만 yield는 잠시 함수 바깥의 코드가 실행되도록 양보하여 값을 가져가게 한 뒤 다시 제너레이터 안의 코드를 계속 실행하는 방식이다.
다음은 range(횟수)처럼 동작을 하는 제너레이터다.
def number_generator(stop):
n = 0 # 숫자는 0부터 시작
while n < stop: # 현재 숫자가 반복을 끝낼 숫자보다 작을 때 반복
yield n # 현재 숫자를 바깥으로 전달
n += 1 # 현재 숫자를 증가시킴
for i in number_generator(3):
print(i)
# 실행 결과
0
1
2
다음은 리스트에 들어있는 문자열을 대문자로 변환하여 함수 바깥으로 전달한다.
def upper_generator(x):
for i in x:
yield i.upper() # 함수의 반환값을 바깥으로 전달
fruits = ['apple', 'pear', 'grape', 'pineapple', 'orange']
for i in upper_generator(fruits):
print(i)
# 실행 결과
APPLE
PEAR
GRAPE
PINEAPPLE
ORANGE
yield에 무엇을 지정하든 결과만 바깥으로 전달한다(함수의 반환값, 식의 결과).
yield from에는 반복 가능한 객체, 이터레이터, 제너레이터 객체를 지정한다.
yield from 반복가능한객체
yield from 이터레이터
yield from 제너레이터객체
def number_generator():
x = [1, 2, 3]
yield from x # 리스트에 들어있는 요소를 한 개씩 바깥으로 전달
for i in number_generator():
print(i)
# 실행 결과
1
2
3
def number_generator(stop):
n = 0
while n < stop:
yield n
n += 1
def three_generator():
yield from number_generator(3) # 숫자를 세 번 바깥으로 전달
for i in three_generator():
print(i)
# 실행 결과
0
1
2