Совместная процедура возвращает None для каждой альтернативной итерации - PullRequest
0 голосов
/ 03 апреля 2020

У меня есть фрагмент кода, как показано ниже:

#!/bin/python3

import math
import os
import random
import re
import sys
import logging


def consumer():
    while True:
        x = yield
        print(x)

def producer(n):
    for _ in range(n):
        x = int(input())
        yield x


def rooter():
    logging.info("Running the rooter")
    while True:
        value = (yield)
        yield math.sqrt(value)


def squarer():
    logging.info("Running the squarer")
    while True:
        value = (yield)
        print("from squarer: {}".format(value))
        yield value * value


def accumulator():
    logging.info("Running the accumulator.")
    running_total = 0
    while True:
        value = (yield)
        running_total += value
        yield running_total


def pipeline(prod, workers, cons):
    logging.info("workers: {}".format(workers))
    for num in prod:
        for i, w in enumerate(workers):
            num = w.send(num)
        cons.send(num)
    for worker in workers:
        worker.close()
    cons.close()

if __name__ == '__main__':
    order = input().strip()
    m = int(input())

    prod = producer(m)

    cons = consumer()
    next(cons)

    root = rooter()
    next(root)

    accumulate = accumulator()
    next(accumulate)

    square = squarer()
    next(square)

    pipeline(prod, eval(order), cons)

Пример ввода

[square, accumulate]
3  <- Number of inputs coming further

1  <- actual inputs
2
3

Пример вывода

*The output should be as below:*
1
5
14

, но доходит до 10 (сумма квадратов 1 и 3), когда она должна быть на самом деле 14 (сумма квадратов 1, 2, 3)

Таким образом, по сути, вход 2 отсутствует (это второй в строке входов). При дальнейшей отладке я обнаружил, что это имеет место для каждой альтернативной итерации, а не только для предоставленных здесь входных данных.

Я не могу расшифровать, что происходит. Если это поможет, сопрограмма squarer - это та, которая возвращает None во второй итерации. Буду признателен за любую помощь.

1 Ответ

0 голосов
/ 04 апреля 2020

Я нашел решение для этого.

Дело в том, что мы запускаем сопрограмму после использования в функции pipeline, поэтому код выглядит следующим образом: я пометил строку next(w) в звездочке для ссылка.

#!/bin/python3

import math
import os
import random
import re
import sys
import logging


def consumer():
    while True:
        x = yield
        print(x)

def producer(n):
    for _ in range(n):
        x = int(input())
        yield x


def rooter():
    logging.info("Running the rooter")
    while True:
        value = (yield)
        yield math.sqrt(value)


def squarer():
    logging.info("Running the squarer")
    while True:
        value = (yield)
        print("from squarer: {}".format(value))
        yield value * value


def accumulator():
    logging.info("Running the accumulator.")
    running_total = 0
    while True:
        value = (yield)
        running_total += value
        yield running_total


def pipeline(prod, workers, cons):
    logging.info("workers: {}".format(workers))
    for num in prod:
        for i, w in enumerate(workers):
            num = w.send(num)
            **next(w)**
        cons.send(num)
    for worker in workers:
        worker.close()
    cons.close()

if __name__ == '__main__':
    order = input().strip()
    m = int(input())

    prod = producer(m)

    cons = consumer()
    next(cons)

    root = rooter()
    next(root)

    accumulate = accumulator()
    next(accumulate)

    square = squarer()
    next(square)

    pipeline(prod, eval(order), cons)

Как упомянуто в спецификации PEP , в нем говорится, что yield функции генератора всегда None при возобновлении обычным вызовом next. Поэтому, если явно указать yield, в этом случае он будет готов к немедленной обработке следующего ввода.

...