据我所知,Python中的协程概念,你基本上可以有两种不同的传递数据模式(抱歉,我无法找到或找到更好的术语):
基于发件人的:每个协程都会从“外部”消费数据并将其发送给消费者,例如
def coro(consumer):
while True:
item = yield
consumer.send(process(item))
要构建管道,可以从外部协程到内部生成:
producer(filter(sink()))
基于Receiver的:每个协同程序都会从其参数和产量中消耗数据 它给消费者,例如
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
现在我的问题是:是否有任何理智和简单的方法来统一这两种方法?例如,广播加法器的结果?
答案 0 :(得分:0)
我的猜测是,只能这样做:
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)
。如图所示:
更新:这是另一种让加法器成为生成器的方法:
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