Co-Routines in Python

What are they?
So as discussed in Learning Generators, a generator function is a function with the yield statement instead of the usual return statement. Python generators can also consume values using a (yield) statement. In addition two new methods on generator objects, send and close, create a framework for objects that consume and produce values. Generator functions that define these objects are called co-routines.

How do they work?
Co-routines consume values using a (yield) statement as follows : value = (yield) With this syntax, execution pauses at this statement until the object's send method is invoked with an argument : coroutine.send(data) Then, execution resumes, with value being assigned to the value of ''data. To signal the end of a computation, we shut down a co-routine using the close ''method. This raises a GeneratorExit exception inside the co-routine, which we can catch with a try/except clause.

Differences between generators and co-routines
Co-routines are similar to generators with a few differences. The main differences are: Here is an example of a generator : def fib: a, b = 0, 1 while True: yield a        a, b = b, a + b We would then commonly use it in a for-loop like this: for i in fib: print(i) It is fast and does not put a lot of pressure on memory because it GENERATES the values on the fly rather that storing them in a list.
 * Generators are data PRODUCERS
 * Co-routines are data CONSUMERS

Now if we use yield in the above example, we get a co-routine. def grep(pattern): print("Searching for ", pattern) while True: line = (yield) if pattern in line: print(line) Co-routines consume values which are sent to it.

So what does yield return? Well we have turned it into a co-routine. It does not contain any value initially, instead we supply it values externally.

We supply values by using the .send method : search = grep('coroutine') next(search) search.send("I love you") seach.send("Don't you love me?") search.send("I love coroutines instead!") The send values are accessed by yield. Why did we run next? It is required in order to start the coroutine. Just like generators, co-routines do not start the function immediately. Instead they run it in response to the __next__ and .send methods. Therefore you have to run next so that the execution advances to the yield expression.
 * 1) Output: Searching for coroutine
 * 1) Output: I love coroutines instead!

We can close a co-routine by calling the .close method : search = grep('couroutine') search.close