send() to a generator in a "for" loop with continue(val)??
Michele Simionato
michele.simionato at gmail.com
Sun Apr 19 03:08:50 EDT 2009
On Apr 19, 8:09 am, Michele Simionato wrote:
> Coroutines instead could have been implemented as
> a library, without requiring any syntax change.
Here is a proof of principle, just to make clearer
what I have in mind. Suppose you have the following
library:
$ cat coroutine.py
from abc import abstractmethod
class Coroutine(object):
@abstractmethod
def main(self):
yield
def send(self, value):
if not hasattr(self, '_it'): # first call
self._it = self.main()
self._value = value
return self._it.next()
def recv(self):
return self._value
def close(self):
self._it.close()
del self._it
del self._value
Then you could write coroutines as follows:
$ cat coroutine_example.py
from coroutine import Coroutine
class C(Coroutine):
def main(self):
while True:
val = self.recv()
if not isinstance(val, int):
raise TypeError('Not an integer: %r' % val)
if val % 2 == 0:
yield 'even'
else:
yield 'odd'
if __name__ == '__main__':
c = C()
for val in (1, 2, 'x', 3):
try:
out = c.send(val)
except StopIteration:
break
except Exception, e:
print e
else:
print out
This is not really worse of what we do today with the yield
expression:
$ cat coroutine_today.py
def coroutine():
val = yield
while True:
if not isinstance(val, int):
raise TypeError('Not an integer: %r' % val)
if val % 2 == 0:
val = yield 'even'
else:
val = yield 'odd'
if __name__ == '__main__':
c = coroutine()
c.next()
for val in (1, 2, 'x', 3):
try:
out = c.send(val)
except StopIteration:
break
except Exception, e:
print e
else:
print out
Actually it is clearer, since it avoids common mistakes
such as forgetting the ``val = yield`` line in the coroutine
function and the ``c.next`` line right after instantiation
of the coroutine object, which are needed to initialize
the coroutine correctly.
More information about the Python-list
mailing list