11

http://www.dabeaz.com/coroutines/Coroutines.pdfに従ってコルーチンパイプラインを試しています

sink問題は、印刷するだけでなく、どうすれば価値を得ることができるかということです。

たとえば、このコードを見てください

def coroutine(func):
    def start(*args, **kwargs):
        cr = func(*args, **kwargs)
        next(cr)
        return cr
    return start


@coroutine
def produce(target):
    while True:
        n = (yield)
        target.send(n*10)


@coroutine
def sink():
    try:
        while True:
            n = (yield)
            print(n)
    except GeneratorExit:
        pass


sk = sink()
pipe = produce(sink())

このコードで私は得る:

>>> pipe.send(10)
100

次に、出力するのではなく戻り値を取得したいので、シンクから譲ろうとします:

@coroutine
def sink():
    try:
        while True:
            yield (yield)
    except GeneratorExit:
        pass

しかし、それは機能していないようで、ジェネレーターではなくpipe.send(10)まだ返されます。None

では、戻り値を取得するにはどうすればよいでしょうか。

4

1 に答える 1

1

なぜpipe.sendジェネレーターを返す必要があるのですか? そして、返された値で何をするつもりですか?

それが何であれ、それはで行われるべきsinkです。

ただし、関数を次のように変更できます

@coroutine
def produce(target):
    while True:
        n = (yield)
        yield target.send(n*10)

@coroutine
def sink():
    try:
        while True:
            yield (yield)
    except GeneratorExit:
        pass

によって生成された値を生成するtargetため、出力する代わりにpipe.send(10)単に戻ります。100

しかし、プロデューサーとコンシューマーが混在しているため、頭痛の種になる可能性があります。


あなたのコメントに応えて:

from collections import defaultdict

def coroutine(func):
    def start(*args, **kwargs):
        cr = func(*args, **kwargs)
        next(cr)
        return cr
    return start

@coroutine
def produce(key, target):
    while True:
        n = (yield)
        target.send((key, n*10))

class Sink(object):

    def __init__(self):
        self.d = defaultdict(lambda: None)
        self.co = self.sink()

    def send(self, *args):
        self.co.send(*args)

    @coroutine
    def sink(self):
        try:
            while True:
                key, n = yield
                self.d[key] = max(self.d[key], n)
        except GeneratorExit:
            pass


sk = Sink()
pipeA = produce("A", sk)
pipeB = produce("B", sk)

pipeA.send(10)
pipeA.send(20)
pipeA.send(40)

pipeB.send(20)
pipeB.send(40)
pipeB.send(60)

print sk.d.items() # [('A', 400), ('B', 600)]
于 2013-09-04T12:09:05.160 に答える