[컴][파이썬] yield 와 callback





yield 와 callback

yield 와 callback 은 많이 비슷하다. 실제로 작성하는 code 의 flow 는 많이 닮았다.

하지만, yield 는 직접 control(code 가 수행되는 순서로 보자) 을 제어할 수 있는 keyword 이기 때문에 이녀석이 좀 더 큰 범위에 있다고 보면 되겠다. 쉽게 이야기 하면, yield 로 callback 처럼 event 가 끝난 후에 다시 호출이 되는 구조의 code 를 구성할 수 있다.



callback 이 여러개인 경우

만약에 많은 callback 으로 표현해야 하는 경우, 예를 들면, network 에 대한 작업이 연속적으로 5번 일어나야 한다고 하면, callback 을 5번 이나 작성하게 되는데, 이러면 code 의 가독성이 떨어질 가능성이 많아진다.
하지만, yield 를 사용하면, 연속적으로 하나의 code 를 작성할 수 있어서 가독성도 좋고, 명확하게 하는 일을 보여줄 수 있다.


try/catch 를 한곳에

callback 에 비해 yield 를 이용할 때 또 하나의 장점은 같은 일을 하는 녀석을 하나의 code 처럼 한 function 안에 담을 수 있다. 이로 인해서 try/catch 를 이용할 때도 같은 종류의 exception 을 한 곳에서 try/catch 로 묶어놓을 수 있다.[ref. 1]



Reading a code

request  가 끝나면 doSomething() 을 해라
requests.get(callback=function(){
   doSomething()
})

http_request() 가 끝난 후 doSomething() 을 하겠다. http_request() 가 끝날동안 control 을 일단 양보(yield) 하마, 일단 다른일을 해라, 그 일이 끝나면 내가 doSomething() 을 하겠다.
yield http_request()
doSomething()


callback 을 yield 로 변경

ref. 3에 보면 callback 의 구조를 yield 를 사용하는 구조로 변경한 경우가 있다.(callback 을 yield 로 변경하는 법을 이야기하는 것은 아니다. 이 부분은 tornamdo.gen.coroutine 내부를 살펴보자.)

이 code 로 callback 과 yield 의 flow 의 차이를 느껴볼 수 있다.

class AsyncHandler(RequestHandler):
    @asynchronous
    def get(self):
        http_client = AsyncHTTPClient()
        http_client.fetch("http://example.com",
                          callback=self.on_fetch)

    def on_fetch(self, response):
        do_something_with_response(response)
        self.render("template.html")


class GenAsyncHandler(RequestHandler):
    @gen.coroutine
    def get(self):
        http_client = AsyncHTTPClient()
        response = yield http_client.fetch("http://example.com")
        do_something_with_response(response)
        self.render("template.html")



Reference

  1. A Study on Solving Callbacks with JavaScript Generators
  2. 쿠...sal: [컴][파이썬] python 의 Future 가 동작하는 방법
  3. tornado.gen — Simplify asynchronous code — Tornado 4.4.2 documentation

댓글 없음:

댓글 쓰기