LangDev

이것은 문서의 이전 버전입니다!


코루틴

코루틴(coroutine)은 루틴에 대한 진입과 반환이 한 번씩밖에 일어나지 않는 서브루틴(subroutine)과 달리, 진입과 반환이 여러 번 일어나는 코드 조각을 뜻합니다.

파이선

파이선 구현 중 스택리스 파이선을 사용하거나 그린릿(greenlet)을 쓰면 코루틴을 이용할 수 있습니다. 하지만 파이선에서 일반적으로 사용되는 코루틴은 생성자(generator)라고 불리는 구조입니다.

def chatterbox(name):
    yield "Hello, "
    yield name
    yield "!"

보통 함수는 return 문을 이용해 하나의 값을 반환하면서 실행이 종료됩니다. 하지만 생성자는 yield 문을 써서 “여러 번 반환”합니다. 이렇게 여러 번 반환되는 값들은 일반적인 함수의 반환값을 얻을 때와는 다른 접근으로 받아 냅니다.

for i in chatterbox("Foo"):
    print (i)

코루틴이 할 수 있는 모든 일을 생성자가 다 할 수 있는 것은 아닙니다. 하지만 일반적으로 코루틴을 사용하는 용도는 대개 생성자로 충족되고, 생성자는 쓰기 간편하므로 인기가 있습니다.

파이선에는 리스트, 순서쌍, 사전 등 여러 개의 값을 집어 넣을 수 있는 내장 자료 구조가 많이 있으므로, 값 여러 개를 반환할 필요가 있다면 그냥 그런 자료 구조에 값 여러 개를 집어 넣어서 반환하면 되지 않겠느냐는 의문이 들 수도 있습니다. 시퀀스에 비해 생성자가 갖는 장점은 예를 들면 다음과 같은 것입니다.

def counter(bound):
    i = 0
    while i != bound:
        yield i
        i += 1

이 생성자는 0에서 bound까지의 숫자를 하나씩 뱉어 낼 것입니다. 물론 비슷한 코드를 다음과 같이 작성할 수도 있습니다.

def counter_seq(bound):
    i = 0
    r = []
    while i != bound:
        r.append(i)
        i += 1
    return r

그리고 이렇게 해서 만들어진 생성자나 시퀀스를 처음 다섯 항만 출력하는 코드를 짜면, 똑같은 형태가 될 것입니다.

i = 0
for element in counter(1000): # or counter_seq(1000)
    print i
    i += 1
    if i == 5: break

하지만 counter(1000) 코드를 쓸 때와 counter_seq(1000) 코드를 쓸 때에는 실행 상에 엄청난 차이가 있습니다. counter(1000) 코드는 정확히 처음 다섯 항만 계산한 뒤 종료되는 반면 counter_seq(1000) 코드는 천 개의 항을 모두 계산해야 합니다. 코루틴과 서브루틴의 가장 중요한 차이는 이것입니다. 서브루틴은 반환의 기회가 한 번뿐이므로 반환 전까지 모든 계산을 마쳐야 합니다. 반면 코루틴은 여러 번 반환할 수 있으므로 그때 필요한 계산만 하면 됩니다.

심지어 코루틴으로는 다음과 같은 코드도 안전하게 짤 수 있습니다.

def infinite():
    i = 0
    while True:
        yield i
        i += 1

이 생성자는 0에서 시작하여 양의 정수를 하나씩 무한히 뱉어 낼 것입니다. 함수로 만들었다면 호출하는 즉시 무한 루프에 빠지게 되지만, 생성자라면 위의 다섯 항만 출력하는 예제에서 보듯 값을 필요한 만큼만 뽑아 쓴 뒤 버려도 됩니다.

맨위로
coroutine.1327156893.txt.gz · 마지막 수정: 2012/01/21 23:41 작성자 han