Quoting from Python Essential Reference, by David Beazley, page 20:
Normally, functions operate on a single set of input arguments. However, a function can also be written to operate as a task that processes a sequence of inputs sent to it. This type of function is known as a coroutine and is created by using the
yield
statement as an expression (yield) as shown in this example:
def print_matches(matchtext):
print "Looking for", matchtext
while True:
line = (yield) # Get a line of text
if matchtext in line:
print line
To use this function, you first call it, advance it to the first (yield), and then start sending data to it using
send()
. For example:
>>> matcher = print_matches("python")
>>> matcher.next() # Advance to the first (yield)
Looking for python
>>> matcher.send("Hello World")
>>> matcher.send("python is cool")
python is cool
>>> matcher.send("yow!")
>>> matcher.close() # Done with the matcher function call
Based on that information, I wrote this code:
#!/usr/bin/python3.2
import sys
def match_text(pattern):
line = (yield)
if pattern in line:
print(line)
x = match_text('apple')
x.next()
for line in input('>>>> '):
if x.send(line):
print(line)
x.close()
But I get an error message like:
Traceback (most recent call last):
File "xxx", line 9, in <module>
matcher.next() # Advance to the first (yield)
AttributeError: 'generator' object has no attribute 'next'
Why doesn't this code (or the code from the book, for that matter) work in Python 3.2? It seems that what is supposed to be a coroutine, is treated as a generator instead - why? What is going on here?