Что предлагают сопрограммы в 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 и уведомляет потребителей, которые затем распечатывают свое имя, за которым следует значение счетчика.


person Henry Gomersall    schedule 15.04.2011    source источник
comment
Отличная работа для вашего первого вопроса! Спасибо!   -  person jathanism    schedule 15.04.2011


Ответы (1)


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

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

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

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

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
person nimrodm    schedule 15.04.2011
comment
Ах я вижу. Справедливо ли сказать, что преимущества именно такого рода? Нет принципиальной причины, по которой это нужно делать? В частности, любая зависимость от состояния, которая у меня, вероятно, будет, будет зависеть от времени выполнения, поэтому в любом случае ее нужно будет связать с логикой внутри сопрограммы. - person Henry Gomersall; 15.04.2011
comment
Уже существует так много способов сделать что-то, используя парадигму потребитель/производитель, что нет необходимости делать это так. Рассмотрение того, нужна ли вам многопоточность, многопроцессорность или и то, и другое, должно помочь вам решить, что лучше для вас. Самый простой подход к выполнению работы обычно (обычно!) лучший. - person jathanism; 15.04.2011