FANDOM


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 :

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-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()

ReferencesEdit

Coroutines - pythontips.com

Coroutines and Tasks - docs.python.org

Why do we need coroutines in python? - Stackoverflow

Python Coroutines - wla.berkley.edu

Community content is available under CC-BY-SA unless otherwise noted.