Hello Pythonistas, Lets dive into chain of responsibility pattern.

Its in fact pretty easy to understand. As shown in diagram above. We have chain of handlers , once the event is generated , its passed to the first handler in chain.

If the handler is able to process the event, the event gets consumed but if the handler is unable to process the event, handler then passes this event to the next handler in chain.

The bottom line is handlers should pass the event that they cant process, to next handler in chain

This can be achieved by traditional way using classes for handlers and making them implement a common process method but in this post we are going to see how coroutines can be used as handlers and how can we form chain of coroutines.

This recipe is present in book Python in Practice. I would highly encourage everyone reading this book.

Before we look at the recipe, lets refresh our knowledge of generators and corotuines in Python.

Generators: Any python function with yield keyword is a generator. Generators are actually producer of items. They not only produce the item , but they yield control back to the client so that client can process it. Generators are driven by client : What i mean by that is , unless client asks for the next item , Generators wont produce the next item. This is significatnly important cause it drastically reduces the memory footprint and avoids unnecessary processing of the items at the source just to find out later that client is interested in only of subset of it. To drive the point home, client pulls the item out of generator cause generator is the producer of item upon clients request. yield item

Coroutines: If you look at coroutines , they look pretty similar to generators by the semantics. Yes they have the yield keyword in their function body. But the way it appears is definitely different, its on the right side of an expression. item = yield Fundamental difference when comapred to generators, is that client pushes value into coroutines and it remains suspended till client pushes new value coro.send(10)

Now that we have basics of Generators and Coroutines under the belt lets move on to seeing how we can code chain of responsibility using coroutines.

So to develop an intuition around it, for chain of responsibility we need chain of handlers and we need to be able to push event to first and subsequent handlers based on the current handler was able to process it or not.

So what if our couroutines knew whom to pass the event if they are not able to handle the pushed event, the current coroutine becomes client(pusher) for the next coroutine.

Also if current coroutine is able to handle the pushed item or not, can be any condition; simple or complex and in our example its as simple as string comparison.

Now as show below we have three events and three distinct handlers for that SongHandler->ImageHandler->SlackHandler to handle these events.

every handler takes its successor as an input and thus we are able to make chain.

pipeline = SongHandler ( ImageHandler ( SlackHandler ()))

Now go ahead and give below code a good read and i am sure you will be able to appreciate the beauty of the solution.