Using generator send with for semantics

时间:2017-10-12 10:10:14

标签: python-3.x generator yield

I would like to use the following generator with a for loop instead of a while, exploiting the fact that for implicitly calls next() and handles StopIteration on generators:

def gen():
    failures = 0
    ret = 0
    while True:
        yield ret
        x = yield
        ret += 1
        if not x:
            failures += 1
            if failures == 20:
                break

The main idea of this generator is sending a value and expecting a "feedbak" on the value. After 20 negative feedbacks, the generator terminates.

Now, I would expect this to be easily usable in a for loop as follows:

g = gen()
for k in g:
    print(k)
    if k % 2:
        g.send(False)
    else:
        g.send(True)

the idea being yield ret is done every time the for implicitly calls next() and x = yield is done every time g.send() is called. Unfortunately, this does not work: in fact, for some reason, the generator always receives None from the send. The only way I managed to get this to work is changing the generator as follows:

def gen():
    failures = 0
    ret = 0
    while True:
        x = yield ret  # this changes
        ret += 1
        if not x:
            failures += 1
            if failures == 20:
                break

and using it like this:

g = gen()
k = g.send(None)
while True:
    try:
        print(k)
        if k % 2:
            k = g.send(False)
        else:
            k = g.send(True)
    except StopIteration:
        break

Is there any way to accomplish this using for semantics to implicitly handle the generator's termination?

0 个答案:

没有答案