제너레이터는 지연 평가(lazy evaluation) 구현체이다.
파이썬에서 모든 lazy evalution은 이터레이터(iterator)라고 불린다. 이러한 이터레이터 중에서 특정 방식을 통해서 생성한 이터레이터를 제너레이터라고 부른다. |
즉, 객체의 값을 미리 생성해서 저장해 두지 않고 해당 객체를 사용할 때 값을 계산해서 반환해준다.
제너레이터는 소괄호()를 이용한 컴프리헨션으로 생성할 수 있다.
num = (x for x in range(10))
print(num)
>><generator object <genexpr> at 0x00000214166F4AC8>
위의 설명처럼 객체를 사용할 때 값을 계산해주므로 for문으로 제너레이터를 사용해보면
num = (x for x in range(10))
for x in num:
print(x, end=' ')
>>0 1 2 3 4 5 6 7 8 9
next함수로도 제너레이터의 사용이 가능하다. next함수는 제너레이터의 다음 값을 반환해준다.
num = (x for x in range(3))
print(next(num))
print(next(num))
print(next(num))
>>0
>>1
>>2
정해진 범위를 벗어나면 StopIteration 에러가 발생한다.
num = (x for x in range(3))
print(next(num))
print(next(num))
print(next(num))
print(next(num))
>>0
1
2
Traceback (most recent call last):
File "..............................", line 5, in <module>
print(next(num))
StopIteration
제너레이터는 다른 이터레이터(iterator)와 달리 값을 계산해서 반환해주고 나면 값을 소비하고 더 이상 기억하지 않는다.
(재사용이 불가능하다.)
num = (x for x in range(10))
for x in num:
print(x, end=' ')
for x in num: #두 번째 for문에서는 아무것도 출력이 되지않는다.
print(x, end=' ')
>>0 1 2 3 4 5 6 7 8 9
yield를 이용한 제너레이터 생성
def문을 이용한 함수 내부에 yield 키워드를 사용하여 제너레이터의 생성이 가능하다.
아래와 같이 값을 단순 지정해줄 수도 있고
def gen():
yield 0
yield 1
yield 2
x=gen() #제너레이터 x 생성
for i in x:
print(i)
>>0
1
2
보통 함수와 같이 내부에 for문과 if문을 사용할 수도 있다.
def gen():
for i in range(3):
yield i
x=gen()
for i in x:
print(i)
>>0
1
2
파이썬은 함수 내부에 yield 키워드가 하나라도 존재하면 해당 함수를 generator로 인식한다. |
아래와 같이 함수에 인자를 받으면 더 다양한 제너레이터를 생성할 수 있다.
또한 반복문을 이용하여 매번 다른 값을 생성하여 반환해준다면 재사용도 가능할 것이다.
import random
def broken_dice(n): #1~6까지의 주사위 값중 n을 제외하고 리턴
while True:
number = random.randint(1, 6) # 1~6까지 정수 중 랜덤하게 숫자를 뽑는다.
if number != n: # 랜덤하게 뽑은 숫자, n이 아니라면 리턴
yield number
dice=broken_dice(5)
for i in range(6):
print(next(dice))
>>2
2
2
1
1
4
'Python' 카테고리의 다른 글
Python - 컴프리헨션(Comprehension) (0) | 2020.08.25 |
---|---|
Python - 람다함수(익명함수) (0) | 2020.08.24 |
Python - 전역 변수, 지역 변수 (0) | 2020.08.23 |
Python - mutable객체, immutable객체 (0) | 2020.08.22 |
Python - 빠른 입력 (0) | 2020.08.17 |