Что предлагают сопрограммы в python, которые улучшают наивную настройку потребителя / производителя? - PullRequest
4 голосов
/ 15 апреля 2011

Я немного прочитал о сопрограммах, в частности, с 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 это, похоже, не проблема.

Может кто-нибудь пролитьсвет на это для меня?Спасибо.

edit: Извинения, производитель в приведенном выше коде считает от 0 до 9 и уведомляет потребителей, которые затем распечатывают их имя, за которым следует значение счетчика.

1 Ответ

4 голосов
/ 15 апреля 2011

При использовании подхода сопрограмм и код потребителя, и код производителя иногда могут быть проще.В вашем подходе, по крайней мере, один из них должен быть записан как конечный автомат (при условии, что какое-то состояние задействовано).

При подходе сопрограмм они являются по существу независимыми процессами.

Пример может помочь:

Возьмите приведенный вами пример, но теперь предположим, что потребитель печатает только каждый второй ввод.Ваш подход требует добавления члена объекта, указывающего, является ли полученный ввод нечетным или четным.

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
...