몇 년 전에 yield
키워드에 대한 글을 쓴 적이 있습니다.
근데 이 글을 쓴 뒤로 잊을만 하면 받은 질문이 있습니다.
그럼 yield from은 뭐에요?
그 질문에 답하는 글을 써보려고 합니다.
보통 이걸 어디서 보냐 하면.
사실 Python을 가볍게 쓰면 yield from
은 그다지 쓸 일이 없습니다.
가장 많이 조우하게 되는 곳은 asyncio
기반의 코드들이죠.
@asnycio.coroutine
def coro():
yield from asyncio.sleep(1)
print('Hello world!')
뭔가 실행할 때 마다 앞에 붙이는데, 안 붙이면 돌아가지 않습니다.
사실 이 시점에선 그냥 비동기 작업에는 모두 붙여야한다고 생각하고 넘겨도 될 것 같습니다만 그렇게 생각하신 분들은 이 글을 찾지 않으셨겠죠.
원래 용도.
yield from
은 PEP-380에 제안되어 Python 3.3에서 처음 소개된 문법입니다.
정말 단순하게 말하자면 yield from은 다음과 같습니다.
def gen1():
for x in range(10):
yield x
for x in range(5):
yield x
def gen2():
yield from range(10)
yield from range(5)
for a, b in zip(gen1(), gen2()):
assert a == b
여기서 gen1
과 gen2
는 동일한 동작을 합니다. (따라서 아래 루프에서도 에러가 발생하지 않습니다.)
generator 여러개를 이어 붙인다던가 하는 상황에 유용하게 쓸 수 있습니다.
반복문을 써서 yield
를 일일히 해주는 경우와 yield from
을 쓰는 경우의 차이점이 있다면 send
로 값을 주고 받는 경우인데, send된 값은 가장 바깥의 yield
로 전송됩니다.1
이게 왜 asyncio랑 쓰이죠?.
asyncio
는 비동기 프로그래밍을 위해 개발되어 Python 3.4에서 추가된 빌트인 모듈입니다.
가장 큰 특징은 손쉬운 비동기 프로그래밍을 위해 코루틴을 사용한다는 점입니다.
코루틴(Coroutine)은 다중진입점을 가집니다. 실행하다가 중간에 끊고 다른 작업을 하다가 다시 원래 위치로 돌아올 수 있죠.
Python에서 코루틴을 구현하려면 Generator를 써야합니다.
yield
문을 통해 다중진입점을 구현한 것이죠.
이러한 코루틴을 동작시키고, 실행결과를 받아서 사용하려면 yield from
을 사용해야만 하는 것이죠.
하지만 Python 3.5 부터는 await
구문이 추가됩니다.
코루틴을 쓰는 목적이라면 await
을 쓰는 쪽이 더 편해져서 yield from
은 쓰지 않게 되었습니다.2
요약.
yield from
은 Generator를 넘기는 용도로 사용한다.- 반복문을 이용해
yield
한것과 비슷하지만yield
가 아니기 때문에send
시 동작이 다르다. - 비동기 코드 작성에 쓰였었지만 Python 3.5부터는
await
에 대체되었다.
말미.
이 글을 보고 궁금함이 하나 해소되었지만 “코루틴이 그래서 뭐야?” 같은 다른 궁금함이 여러개 생겨버린 분들을 위한 부가 설명을 담은 글은 다음 기회에 별도의 작성하겠습니다.
각주.
-
자세한 점은 What’s New in Python 3.3의
yield from
소개 단락을 참조 원래 위치로 -
하지만 대다수의 비동기 라이브러리들은 하위 호환성을 위해 아직도
yield from
을 사용합니다. 원래 위치로