[Python] generators

최창현·2022년 2월 1일
0
post-thumbnail

generators

파이썬에서 보통의 함수는 값을 반환하고 종료하지만 제네레이터 함수는
값을 반환하기는 하지만 산출(yield)한다는 차이점이 있다. 그리고 제네레이터는
쉽게 얘기하면 이터레이터를 생성해주는 함수라고도 볼 수 있다.

다음 코드를 보면 함수안에서 yield를 사용하여 리스트의 제곱을 산출하는 함수가 있고, 이 함수를 print문으로 확인해보면 generator object임을 확인할 수 있다.

def generator_squares():
    for i in range(3):
        yield i ** 2
print("gen object=", end=""), print(generator_squares())
>>gen object=<generator object generator_squares at 0x000001BA64555AC0>

Yield?

yield는 제네레이터 함수에서 값을 반환할 때 사용되며 yield 호출후에 다시
next가 호출될때 까지 현재의 상태에서 머물고 있다가 next 함수가 호출되면
이전의 상태에 이어서 다음 연산을 수행한다.
generator를 dir로 함수종류를 확인해보면 이터레이터와는 다르게 iternext함수가 둘다 들어있는 것을 확인할 수 있다.

print("dir gen=", end=""), print(dir(generator_squares()))
>>dir gen=['__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']

그래서 이터레이터에서 처럼 iter를 호출한 후에 next 함수를 호출하지 않아도
next 를 바로 호출할 수 도 있다.

gen = generator_squares()
print(gen.__next__())
print(gen.__next__())
print(gen.__next__())
print(gen.__next__())
>>0
1
4
Traceback (most recent call last):
File "C:\Users\Choi\AppData\Local\Programs\Python\Python39\practice.py", line 17, in <module>
print(gen.__next__())
StopIteration

이터레이터와 마찬가지로 next함수로 값을 꺼내올 수 있고 for 문이 끝나게 되면
StopIteration 이 발생한다. 그리고 제너레이터 함수는 실행중에 send 함수를 통해서
값을 전달받을 수 있다.

send함수로 값을 전달하는 코드는 다음과 같다.

def generator_send():
    received_value = 0
    while True:
        received_value = yield
        print("received_value = ", end=""), print(received_value)
        yield received_value * 2
gen = generator_send()
next(gen)
print(gen)
print(gen.send(2))
next(gen)
print(gen.send(3))
>>
<generator object generator_send at 0x000001FE12B4BC10>
received_value = 2
4
received_value = 3
6

generator_send 함수는 yield로 send를 통해서 받은 값을 received_value에 할당하고
그 값의 2배 수를 리턴받고 있다. 제네레이터에서는 이처럼 yield를 이용해서 제네레이터 함수
실행중 값을 전달할 수 있고, 응용하면 제네레이터 함수를 사용해서 main 실행 루프에서 연산결과에
따라 호출도 제어할 수 있다.


제네레이터 표현식(generator expression)

제네레이터 함수 외에도 제네레이터 표현식이 있다. 제너레이터 표현식은 Lazy evalution을 위해 사용될 수 있다. Lazy evaluation은 말그대로 실행을 지연시킨다는 의미이다.

profile
chch_oi

0개의 댓글