Python 协程给出未知的 None 产量

Python coroutines gives unknown None on yield

我正在尝试根据用户输入构建一些数学运算的管道,并尝试打印此运算的累积结果。 例如,输入将是一个操作列表,然后是数字输入的数量,然后是这样的数字:

[square, accumulate]
3
1
2
3

这应该return类似于:

1
5
14

首先将 1 打印为 1*1,然后将 1 与 2*2 的结果相加得到 5,然后将其与 3*3 相加得到 14。 但是我的方法有问题,第二个数字输入总是变成 None 值,我不知道为什么。 我卡住了:

1
None
10

有什么想法吗?这是我的代码:

import math
import os
import random
import re
import sys

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

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

def get_root():
    while True:
        number = (yield)
        yield math.floor(math.sqrt(number))

def get_square():
    number = 0
    while True:
        number = (yield)
        yield number**2

def accumulator():
    acum = 0
    while True:
        acum += (yield)
        yield acum

def operations_pipeline(numbers, operations, print_acum):
    for num in numbers:
        for i, w in enumerate(operations):
            num = w.send(num)
        print_acum.send(num)
    for operation in operations:
        operation.close()
    print_acum.close()

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

    numbers = co_generator(n)

    print_acum = printer()
    next(print_acum)

    root = get_root()
    next(root)

    accumulate = accumulator()
    next(accumulate)

    square = get_square()
    next(square)

    operations_pipeline(numbers, eval(order), print_acum)

我认为您需要在此处的 operations_pipeline 代码中添加对 next 的调用:

def operations_pipeline(numbers, operations, print_acum):
    for num in numbers:
        for i, w in enumerate(operations):
            num = w.send(num)
            next(w) # <<<--- this

如果没有它,我不相信它会第二次回到 get_square,假设您的第一个输入是 [square, accumulate]

您正在编写您的代码,就好像 (yield) 接收一个值并且 yield whatever 发送一个值。它不是这样工作的。 所有 yield 都发送一个值并接收一个值。

当生成器执行 yield 时,它分两个阶段进行。首先,yield 的参数变为当前 nextsend 调用的 return 值,生成器暂停执行。如果没有参数,则使用 None。这就是您的 None 的来源

其次,当另一个 nextsend 被执行时,生成器取消挂起,并且 send 参数(或 None 如果使用 next ) 成为 yield 表达式的值。

您正在尝试使用一个 yield 来接收 send 参数,并使用另一个来设置 send 的 return 值。您需要使用单个 yield 来设置 send return 值并接收下一个 send 的参数。例如,

def get_square():
    number = 0
    while True:
        number = yield number**2

或者,如果您想在生成器端使用单独的 yield 发送和接收值,则需要使用单独的 send(或 next)调用在另一端接收和发送值,并忽略 Nones。例如,

w.send(num)
num = next(w)

而不是 num = w.send(num),所以 operations_pipeline 看起来像

def operations_pipeline(numbers, operations, print_acum):
    for num in numbers:
        for w in operations:
            w.send(num)
            num = next(w)
        print_acum.send(num)
    for operation in operations:
        operation.close()
    print_acum.close()
def rooter():
    number=0
    while True:
        number= yield math.floor(math.sqrt(number))
    

def squarer():
    number=0
    while True:
        number= yield number**2

yield will give none try this way

def accumulator():
    number=0
    while True:
        number+= yield number