43.1 코루틴에 값 보내기

코루틴은 제네레이터의 특별한 형태입니다. 제네레이터는 yield로 값을 발생시켰지만 코루틴은 yield로 값을 받아올 수 있습니다. 다음과 같이 코루틴에 값을 보내면서 코드를 실행할 때는 send 메서드를 사용합니다. 그리고 send 메서드가 보낸 값을 받아오려면 yield를 괄호로 묶어준 뒤 변수에 저장합니다.

  • 코루틴객체.send(값)
  • 변수 = (yield)

그럼 코루틴에 숫자 1, 2, 3을 보내서 출력해보겠습니다.

coroutine_consumer.py

def number_coroutine():
    while True:        # 코루틴을 계속 유지하기 위해 무한 루프 사용
        x = (yield)    # 코루틴 바깥에서 값을 받아옴
        print(x)
 
co = number_coroutine()
next(co)      # 코루틴 안의 yield까지 코드 실행(최초 실행)
 
co.send(1)    # 코루틴에 숫자 1을 보냄
co.send(2)    # 코루틴에 숫자 2을 보냄
co.send(3)    # 코루틴에 숫자 3을 보냄

실행 결과

1
2
3

먼저 코루틴 number_coroutinewhile True:로 무한히 반복하도록 만듭니다. 왜냐하면 코루틴을 종료하지 않고 계속 유지시키기 위해 무한 루프를 사용합니다(코루틴을 종료하는 방법은 뒤에서 설명하겠습니다). 그리고 x = (yield)와 같이 코루틴 바깥에서 보낸 값을 받아서 x에 저장하고, printx의 값을 출력합니다.

def number_coroutine():
    while True:        # 코루틴을 계속 유지하기 위해 무한 루프 사용
        x = (yield)    # 코루틴 바깥에서 값을 받아옴
        print(x)

코루틴 바깥에서는 co = number_coroutine()과 같이 코루틴 객체를 생성한 뒤 next(co)로 코루틴 안의 코드를 최초로 실행하여 yield까지 코드를 실행합니다(co.__next__()를 호출해도 상관없습니다).

  • next(코루틴객체)
co = number_coroutine()
next(co)      # 코루틴 안의 yield까지 코드 실행(최초 실행)

그다음에 co.send로 숫자 1, 2, 3을 보내면 코루틴 안에서 숫자를 받은 뒤 print로 출력합니다.

co.send(1)    # 코루틴에 숫자 1을 보냄
co.send(2)    # 코루틴에 숫자 2을 보냄
co.send(3)    # 코루틴에 숫자 3을 보냄

그럼 코루틴의 동작 과정을 그림으로 살펴보겠습니다.

먼저 next(co)로 코루틴의 코드를 최초로 실행하면 x = (yield)yield에서 대기하고 다시 메인 루틴으로 돌아옵니다.

그림 43-3 코루틴의 코드를 최초로 실행한 뒤 메인 루틴으로 돌아옴
그림 43 3 코루틴의 코드 최초로 실행한 뒤 메인 루틴으로 돌아옴

그다음에 메인 루틴에서 co.send(1)로 1을 보내면 코루틴은 대기 상태에서 풀리고 x = (yield)x = 부분이 실행된 뒤 print(x)로 숫자를 출력합니다. 이 코루틴은 while True:로 반복하는 구조이므로 다시 x = (yield)yield에서 대기합니다. 그러고나서 메인 루틴으로 돌아옵니다. 이런 과정으로 send가 보낸 값을 (yield)가 받게 됩니다.

그림 43-4 send로 값을 보내면 코루틴에서 값을 받아서 출력
그림 43 4 send로 값을 보내면 코루틴에서 값을 받아서 출력

계속 같은 과정으로 send를 사용하여 값을 보내면 코루틴에서 값을 받아서 출력합니다.

정리하자면 next 함수(__next__ 메서드)로 코루틴의 코드를 최초로 실행하고, send 메서드로 코루틴에 값을 보내면서 대기하고 있던 코루틴의 코드를 다시 실행합니다.

내용이 조금 어렵죠? 코루틴은 yield에서 함수 중간에 대기한 다음에 메인 루틴을 실행하다가 다시 코루틴을 실행한다는 점만 기억하면 됩니다.

참고 | send로 코루틴의 코드를 최초로 실행하기

지금까지 코루틴의 코드를 최초로 실행할 때 next 함수(__next__ 메서드)를 사용했지만, 코루틴객체.send(None)과 같이 send 메서드에 None을 지정해도 코루틴의 코드를 최초로 실행할 수 있습니다.