【问题标题】:python generator yield statement not yieldpython生成器yield语句不yield
【发布时间】:2020-04-07 04:53:03
【问题描述】:

这是我正在运行的代码:

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 有关,但无法弄清楚原因。有人可以帮忙吗?

【问题讨论】:

  • 需要考虑third_gen.send的返回值
  • “发送值”和“接收值”不是生成器中的单独操作。 send 也接收一个值。

标签: python generator send yield


【解决方案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

【讨论】:

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

我设法通过为infinite_Third() 增加额外的收益使其按您期望的方式工作,但坦率地说,我不知道它为什么工作。

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 值”
  • send 没有发送额外的Nones,并且生成器没有缓冲区。 for 循环执行的 next 调用正在发送额外的 Nones。
猜你喜欢
  • 2021-09-05
  • 2017-07-07
  • 2013-12-16
  • 2010-10-19
  • 1970-01-01
  • 1970-01-01
  • 2013-12-13
  • 2017-11-18
相关资源
最近更新 更多