首页 > 解决方案 > Python协程在产量上给出未知的无

问题描述

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

[square, accumulate]
3
1
2
3

这应该返回类似:

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)

标签: pythonyieldcoroutine

解决方案


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

当生成器执行 ayield时,它分两个阶段执行。首先, 的参数yield成为当前nextsend调用的返回值,生成器暂停执行。如果没有参数,None则使用。那就是你None的 s 来自哪里

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

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

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

或者,如果您想使用单独yield的 s 在生成器端发送和接收值,那么您需要使用单独的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()

推荐阅读