Может ли сопрограмма давать значения в Python? - PullRequest
0 голосов
/ 08 ноября 2018

Итак, я понимаю, как работают generators и coroutines. Вообще говоря, generators производит данные и coroutines потребляет данные. Теперь я пытаюсь объединить обе эти функции.

Я определил coroutine, который получает list в качестве входных данных и затем пытается **yield** элементов из списка по одному, как generator.

Вот мой код -

def coroutine():
    print('Starting coroutine')
    value = (yield)
    for i in value:
        yield i



c=coroutine()
c.__next__()
c.send([1,2,3,4,5])


for val in c:
    print(val)

Проблема в том, что первый элемент списка теряется. value 1 не возвращается из сопрограммы.

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

  1. c=coroutine() ----> Объявляет coroutine без его запуска.
  2. c.__next__() ----> Это запускает coroutine и продвигается к линии - value = (yield) и останавливается там.
  3. c.send([1,2,3,4,5]) ----> Это передает новый list ожидающей сопрограмме, т.е. value = (yield). Сопрограмма теперь переходит к следующему оператору yield внутри цикла for.
  4. Цикл for в основной программе должен принимать каждый элемент списка, который он первоначально пропустил. Но этого не происходит.

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

Пожалуйста, помогите.

РЕДАКТИРОВАТЬ --------------------

Вывод следующий -

Starting coroutine
2
3
4
5

1 Ответ

0 голосов
/ 08 ноября 2018

Вам не хватает того, что при звонке на send, сопроводитель будет идти до следующего yield, и тот будет вызываться, поэтому, если вы сделаете:

c=coroutine()
c.__next__()
print(c.send([1,2,3,4,5]))


for val in c:
    print(val)

Вы увидите, как печатается пропущенное значение (как оно получено в вызове send)

Здесь у вас есть живой пример

Для желаемого поведения вы можете добавить дополнительный оператор yield к сообщению:

def coroutine():
    print('Starting coroutine')
    value = (yield)
    yield
    for i in value:
        yield i
...