如何统一基于发送方和接收方的协同程序?

2024-04-27 04:50:13 发布

您现在位置:Python中文网/ 问答频道 /正文

就我对Python中的协程概念的理解而言,基本上可以有两种不同的数据传递模式(抱歉,我找不到更好的术语):

  1. 基于发送者的:每个协同程序使用来自“外部”的数据并将其发送给消费者,例如

    def coro(consumer):
        while True:
            item = yield
            consumer.send(process(item))
    

    为了建造管道,我们将从外部到内部生产:

    producer(filter(sink()))
    
  2. 基于接收器的:每个协程消耗来自其参数的数据并产生 它是给消费者的,例如

    def coro(producer):
        while True:
            item = next(producer)
            yield process(item)
    

    要建造管道,就要从内部到外部协同生产, 最终看起来更符合人们对功能的期望:

    sink(filter(producer()))
    

两种方法都有各自的优点。有了基于发送者的协同程序,我可以 向许多消费者广播

    def broadcast(consumers):
        while True:
            item = yield
            for consumer in consumers:
                consumer.send(item)

然而,基于发送者的协同程序总是被限制为一个“输入”协同程序 因为他们分不清是谁给他们寄来了什么(好吧,实际上是的,但那是真的) 会很恶心)。另一方面,这对于基于接收器的系统来说是微不足道的 协同程序:

    def adder(producer1, producer2):
        while True:
            x = next(producer1)
            y = next(producer2)
            yield x + y

现在我的问题是:有没有一种理智而简单的方法来统一这两种方法?例如广播加法器的结果?你知道吗


Tags: producer数据方法trueconsumerdef消费者item
1条回答
网友
1楼 · 发布于 2024-04-27 04:50:13

我猜只有这样做才有可能:

def adder(producer1, producer2, consumers):
    while True:
        x = next(producer1)
        y = next(producer2)
        for consumer in consumers:
            consumer.send(x+y)

然后打电话给adder(x_producer, y_producer, consumers)。如图所示:enter image description here

加法器不能放在流水线的中间,原因是它必须有消费者和生产者的所有参考,如果我们把加法器称为最高级别的加法器,这是可能的。你知道吗

更新:这里是另一种方法,它使加法器成为生成器:

class AdderWithBroadcast(object):

    consumers = []

    def __init__(self, x_prod, y_prod):
        self.x_prod = x_prod
        self.y_prod = y_prod

    def __iter__(self):
        return self

    def next(self):
        x = next(self.x_prod)
        y = next(self.y_prod)

        for consumer in self.consumers:
            consumer.send(x+y)

        return x+y

    def consumer():
        while True:
            a = (yield)
            print a, ' in consumer'


k = iter(range(10))
adder = AdderWithBroadcast(k, k)
cons = consumer()
cons.send(None)
adder.consumers.append(cons)
for i in adder: 
    #  I won't include the actual result here, you can try in no your own
    print i

装饰方法:

class Broadcaster(object):

    consumers = []

    def __init__(self, gen):
        self.gen = gen

    def __iter__(self):
        return self

    def __call__(self, *args, **kwargs):
        self.gen = self.gen(*args, **kwargs)

    def next(self):
        yielded = next(self.gen)

        for consumer in self.consumers:
            consumer.send(yielded)

        return yielded


@Broadcaster
def adder(producer1, producer2):
        while True:
            x = next(producer1)
            y = next(producer2)
            yield x + y
#  result is the same as in previous solution

相关问题 更多 >