Python中的协程为简单的消费者/生产者模式提供了什么改进?
我对协程有一点了解,特别是在Python中,但有些地方我还是不太明白。
我实现了一个生产者/消费者模型,下面是一个基本的版本:
#!/usr/bin/env python
class MyConsumer(object):
def __init__(self, name):
self.__name = name
def __call__(self, data):
return self.observer(data)
def observer(self, data):
print self.__name + ': ' + str(data)
class MyProducer(object):
def __init__(self):
self.__observers = []
self.__counter = 0
def add_observer(self, observer):
self.__observers.append(observer)
def run(self):
while self.__counter < 10:
for each_observer in self.__observers:
each_observer(self.__counter)
self.__counter += 1
def main():
consumer_one = MyConsumer('consumer one')
consumer_two = MyConsumer('consumer two')
producer = MyProducer()
producer.add_observer(consumer_one)
producer.add_observer(consumer_two)
# run
producer.run()
if __name__ == "__main__":
main()
显然,MyConsumer也可以有生产的功能,这样就可以很容易地建立一个数据管道。实际上,我定义了一个基类,里面实现了生产者/消费者模型的逻辑,并且在子类中重写了一个处理函数。这使得创建数据管道变得非常简单,因为处理的部分可以清晰地定义和隔离。
这让我觉得这正是协程应用的典型例子,比如在常被引用的教程中提到的:http://www.dabeaz.com/coroutines/index.html。不过,我不太明白协程相比于上面的实现有什么优势。我能理解在一些处理可调用对象比较麻烦的语言中,使用协程会有好处,但在Python中,这似乎不是个问题。
有没有人能给我解释一下这个问题?谢谢。
补充说明:抱歉,上面的代码中,生产者是从0数到9,并通知消费者,消费者然后打印出它们的名字和计数值。
1 个回答
4
使用协程的方法时,消费者和生产者的代码有时可以更简单。在你的方法中,至少有一个部分必须写成有限状态机(假设涉及到某种状态)。
而使用协程的方法,它们基本上是独立的进程。
举个例子:
假设你提供的例子中,消费者只打印每第二个输入。你的方法需要添加一个对象成员来指示接收到的输入是奇数还是偶数。
def observer(self, data):
self.odd_sample = !self.odd_sample
if self.odd_sample:
print str(data)
而使用协程时,只需要循环遍历输入,丢掉每第二个输入。'状态'是通过代码中的当前位置隐式维护的:
while True:
y = producer()
print(y)
y = producer()
# ignore this value