Python生成器中的yield语句未执行。

5

这里是我正在运行的代码:

def infinite_Third() -> Generator:
    num = 1
    while True:
        if num % 3 ==0:
            i = (yield num)
            if i is not None:
                num = i
        num += 1 

if __name__=='__main__':
    third_gen = infinite_Third()
    for i in third_gen:
        print(f"it is {i}")          
        if i>1000:
            break    
        third_gen.send(10*i+1) 

我期望能够看到以下结果:

it is 3
it is 33
it is 333
it is 3333

然而,我实际得到的是:
it is 3
it is 36
it is 366
it is 3666

我认为这可能与在主代码中使用send有关,但是无法找出原因。 有人可以帮忙吗?


2
你需要考虑third_gen.send的返回值。 - JoseKilo
1
“发送值”和“接收值”在生成器中不是分开的操作。send也会接收一个值。 - user2357112
2个回答

1

回复我的评论,我修改了你的主循环

  • 首先,我们发送None来启动生成器并接收第一个值
  • 之后,我们发送一个值并接收下一个值
if __name__ == '__main__':
    third_gen = infinite_Third()
    i = third_gen.send(None)
    while True:
        print(f"it is {i}")
        i = third_gen.send(10*i+1)
        if i > 1000:
            break

它没有给出预期的输出。 - sardok
我花了一些时间才理解你的意思,但我认为输出中只是缺少了第一个 i 值。我已经更新了我的答案。 - JoseKilo
谢谢。所以你放弃了“for”循环;你能澄清一下“for”循环的问题在哪里吗? - datapy
一般来说,如果我要在循环体中修改循环变量,我不会使用for循环。而在这种情况下,使用for i in third_gen:就像在每次迭代时调用third_gen.send(None),因此您的原始示例在每次迭代时都会调用两次send - JoseKilo
所以你最初的例子是在每次迭代中调用了两次 send。你能详细解释一下吗?我仍然不明白为什么没有产生“33”、“333”等结果。 - datapy

0

我通过在infinite_Third()中添加额外的yield使其按照您的期望工作,但坦白地说,我不知道为什么它能够工作。

def infinite_Third() -> Generator:
    num = 1
    while True:
        if num % 3 ==0:
            i = yield num
            if i is not None:
                num = i
            yield
        num += 1

似乎每次调用send()时,都会向生成器缓冲区中添加一个额外的None值,而额外的yield看起来正在消耗它。


我同意你的观察,很想看到一些文件来证实“每次调用send()时,都会向生成器缓冲区添加一个额外的None值”。 - datapy
send 没有发送额外的 None,生成器没有缓冲区。for 循环执行的 next 调用会发送额外的 None - user2357112

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接