What are they? Edit
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?Edit
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 :
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-routinesEdit
Co-routines are similar to generators with a few differences. The main differences are:
- Generators are data PRODUCERS
- Co-routines are data CONSUMERS
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.
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) # Output: Searching for coroutine search.send("I love you") seach.send("Don't you love me?") search.send("I love coroutines instead!") # Output: 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.
We can close a co-routine by calling the .close() method :
search = grep('couroutine') # ... search.close()
Coroutines - pythontips.com
Coroutines and Tasks - docs.python.org
Why do we need coroutines in python? - Stackoverflow
Python Coroutines - wla.berkley.edu