Coroutines
Similar to generators with a few differences:
generators are data producers
coroutines are data consumers
Generator blueprint:
def fib():
a, b = 0, 1
while True:
yield a
a, b = b, a+b
We 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 than storing them in a list.
If we use yield
in the above example, we get a coroutine.
Coroutines consume values which are sent to it.
Example: a grep
alternative in Python:
def grep(pattern):
print("Searching for", pattern)
while True:
line = (yield)
if pattern in line:
print(line)
We have turned it into a coroutine. yield
does not contain any value initially, instead we supply it values externally. We supply values by using the .send()
method. Example:
search = grep('coroutine')
next(search)
# Output: Searching for coroutine
search.send("I love you")
search.send("Don't you love me?")
search.send("I love coroutines instead!")
# Output: I love coroutines instead!
The sent values are accessed by yield
.
next()
is required to start the coroutine. Just like generators
, coroutines 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.
Close a coroutine by calling the .close()
method:
search = grep('coroutine')
# ...
search.close()
Further reading
There is a lot more to coroutines
. I suggest you check out this awesome presentation by David Beazley.
Last updated