1

我有一个消费者生成器的管道。从这些消费者中的最后一个,我想在某个时间点返回结果。这有效:

class StopIterationWithResult(StopIteration):
    def __init__(self, result):
        super(StopIterationWithResult, self).__init__()
        self.result = result

# for definition fo consumer decorator see http://www.python.org/dev/peps/pep-0342/
@consumer
def waitfor3():
    while True:
        value = (yield)
        if value == 3:
            raise StopIterationWithResult('Hello')

c = waitfor3()
for i in range(10):
    try:
        print 'calling', i
        c.send(i)
    except StopIterationWithResult as r:
        print 'stopped', r.result
        break

有没有更好的办法?例如,如果生成器StopIterationreturn语句而引发,您能否访问它的返回值?

根据@alexis 的要求,这是一个带有管道的示例:

class StopIterationWithResult(StopIteration):
    def __init__(self, result):
        super(StopIterationWithResult, self).__init__()
        self.result = result

@consumer
def add1_filter(consumer):
    while True:
        value = (yield)
        consumer.send(value+1)

@consumer
def waitfor3():
    while True:
        value = (yield)
        print 'got', value
        if value == 3:
            raise StopIterationWithResult('Hello')

c = waitfor3()
f = add1_filter(c)
for i in range(10):
    try:
        print 'calling', i
        f.send(i)
    except StopIterationWithResult as r:
        print 'stopped', r.result
        break

这与@Martijn Pieters 的答案相同 - 但是,过滤器有点难看:

@consumer
def add1_filter(consumer):
    result = None
    while True:
        value = (yield result)
        result = consumer.send(value+1)

@consumer
def waitfor3():
    while True:
        value = (yield)
        print 'got', value
        if value == 3:
            yield 'Hello'
            break

c = waitfor3()
f = add1_filter(c)
r = None
for i in range(10):
    try:
        print 'calling', i
        r = f.send(i)
    except StopIteration:
        print 'stopped', r
        break
4

2 回答 2

2

收益是双向的。在右手表达式中使用,它将接收并用作产生表达式结果的语句。

只需产生该结果值:

def waitfor3():
    while True:
        value = (yield)
        if value == 3:
            yield 'Hello'
            break

c = waitfor3()
for i in range(10):
    try:
        print 'calling', i
        result = c.send(i)
    except StopIteration:
        print 'stopped', result
        break
于 2012-12-18T22:30:12.520 回答
0

你不需要子类StopIteration,你可以访问args你传递给它的构造函数。请参阅http://docs.python.org/2/library/exceptions.html#exceptions.BaseException

@consumer
def add1_filter(consumer):
    while True:
        value = (yield)
        consumer.send(value+1)

@consumer
def waitfor3():
    while True:
        value = (yield)
        print 'got', value
        if value == 3:
            # This doesn't work:
            # return 456 # SyntaxError: 'return' with argument inside generator 
            # But this does:
            raise StopIteration(123)

c = waitfor3()
f = add1_filter(c)
for i in range(10):
    try:
        print 'calling', i
        f.send(i)
    except StopIteration as r:
        print 'stopped (StopIteration)', r, type(r.args[0])
        break
于 2012-12-18T23:25:41.367 回答