从消费者 - 生成器返回单个值

时间:2012-12-18 22:16:38

标签: python generator

我有一系列消费者发电机。从最后这些消费者中,我想在某个时间点返回结果。这有效:

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

有更好的方法吗?例如,如果由于StopIteration语句而引发return,则可以访问生成器的返回值吗?

根据@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

2 个答案:

答案 0 :(得分: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

答案 1 :(得分: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