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

より良い方法はありますか?たとえば、ステートメントが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
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アクセスできます。http://docs.python.org/2/library/exceptions.html#exceptions.BaseExceptionargsを参照してください:

@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 に答える