multirember&co
attn.steven.kuo at gmail.com
attn.steven.kuo at gmail.com
Wed Apr 18 14:30:30 EDT 2007
On Apr 17, 3:52 pm, bearophileH... at lycos.com wrote:
(snipped)
>
> So far I haven't succed using the coroutine Python 2.5 allows using
> the generators, and I think still that xsplitter can be done with two
> coroutines instead of two It objects. Despite Steven's code I am
> unable still to write a working code with coroutines (probably because
> I haven't understood how they work yet). This time I take a breath and
> I show my wrong code:
>
> import collections
>
> def xsplitter(iseq, pred):
> def it(parity):
> queue = collections.deque()
> while True:
> received = (yield)
> if received is not None:
> queue.append(received)
> if queue:
> yield queue.popleft()
> else:
> try:
> el = iseq.next()
> if pred(el) == parity:
> yield el
> else:
> its[not parity].send(el)
> except StopIteration:
> raise
>
> its = [it(False), it(True)]
> return its[True], its[False]
>
> idata = iter([1, 'a', 3, 'a', 4, 5, 6, 'a'])
> it1, it2 = xsplitter(idata, lambda x: x == 'a')
>
> from itertools import izip
> for el1, el2 in izip(it1, it2):
> print el1, el2
>
> It prints:
> None None
> None None
> a 3
> None None
> a 4
> None None
> None None
> None None
>
> Can it be fixed? Are you able to fix it for me? (If you want you can
> think of it as an exercise to understand Python coroutines :-) ).
I don't think coroutine are what's needed here. In particular,
using 'send' will *deplete* the iterator -- the very iterator
to which one is trying to add an element.
If you don't wish to use objects, you can replace them with
a closure:
import collections
def xsplitter(iseq, pred):
queue = [ collections.deque(), collections.deque() ]
def it(parity):
while True:
if queue[parity]:
yield queue[parity].popleft()
else:
try:
el = iseq.next()
if pred(el) == parity:
yield el
else:
queue[not parity].append(el)
except StopIteration:
raise
its = [ it(False), it(True) ]
return its[True], its[False]
idata = iter([1, 'a', 3, 'a', 4, 5, 6, 'a'])
it1, it2 = xsplitter(idata, lambda x: x == 'a')
from itertools import izip
for el1, el2 in izip(it1, it2):
print el1, el2
Oh, I and do like your rewrite; it's much less
repetitive and cleaner than my original version.
--
Regards,
Steven
More information about the Python-list
mailing list