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 回答