Python:我不明白这个生成器正在发生什么 [英] Python: I don't understand what's happening with this generator

查看:95
本文介绍了Python:我不明白这个生成器正在发生什么的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我很好奇这里发生的事情。

I'm curious as to what's happening here. Can someone who knows generators and coroutines well explain this code.

def b():
    for i in range(5):
        yield i
        x = (yield)
        print(x)

def a():
    g = b()
    next(g)
    for i in range(4):
        g.send(5)
        print(next(g))

a()

输出

None
1
None
2
None
3
None
4

但是当我在第3行和第4行切换时: yield i x =(yield),我得到以下内容。

but when I switch around lines 3 and 4: the lines yield i and x = (yield), I get the following.

5
None
5
None
5
None
5
None

我怀疑问题可能是我尝试使用yield语句在同一函数中接收和发送值。这在Python中是不可能的吗?

I suspect the problem might me from trying to use the yield statement to both receive and send values in the same function. Is this not possible in Python?

我已经成功编写了两个使用协程的程序,因此我熟悉它们的工作方式,但是对于这段代码的方式却感到困惑表现。

I have successfully written a couple of programs that use coroutines, so I am familiar with the way they work, but I am confused as to the way this snippet of code is behaving. Any insights into this would be appreciated.

谢谢

编辑:谢谢BrenBarn和unutbu的回答。当您这样扩展问题时,这里发生的事情更有意义。

Thanks BrenBarn and unutbu for your answers. What's happening here makes more sense when you expand the problem out as such.

def b():
    for i in range(5):
        yield i
        x = yield None

def a():
    g = b()
    print('* got', g.send(None) )
    for i in range(4):
        print('+ got', g.send(5) )
        print('- got', g.send(None))

a()


推荐答案

我不太了解您的要求,但是基本上:当您使用 send 时,它会在生成器以评估您发送的值。还要注意,发送会使生成器前进到下一个收益。可能使您感到困惑的一件事是,您正在生成器中打印 x 的值,并且正在打印 next(g)的值位于 b 内,但生成器还在 g.send(5)处产生值,而您不会打印这些。

I don't quite get what you're asking, but basically: when you use send, it causes the most-recently-reached yield expression in the generator to evaluate to the value you send. Note also that send advances the generator to the next yield. One thing that may be confusing you is that you are printing the value of x inside the generator, and you are printing the value of next(g) inside b, but the generator is also yielding values at g.send(5), and you aren't printing those.

在您的第一种情况下,第一次发送 c会导致 yield i 语句在 b 中的值为5,但是您不要在 b <中使用此值/ code>(您不会将 yield i 分配给任何东西),因此它什么也没做。另外,当您执行 send(5)时,生成器将产生None(从 x =(yield)行),但您不打印它,所以您不知道这一点。然后,使用 next(g)再次推进生成器。最近达到的收益是 x =收益,但是 next(g)没有传递任何值,因此 x 设置为None。

In your first case, your first send causes the yield i statement to evaluate to 5 inside b, but you don't use this value inside b (you don't assign yield i to anything), so it does nothing. Also, when you do send(5), the generator is yielding None (from the x = (yield) line), but you don't print it so you don't know this. Then you advance the generator again with next(g). The most-recently-reached yield is the x = yield, but next(g) passes no value, so x gets set to None.

在第二种情况下,调用的奇偶校验被颠倒了。现在,您的第一个发送确实发送到了 x = yield 行,所以 x 设置为5。此发送也会在 b 中产生循环值,但是您忽略了该值在 a 中,不要打印它。然后,打印 next(g),即无。在随后的每次发送中, b 会显示 x 的值,该值始终为5,因为这就是您始终发送的值,并且然后 a 会显示 next 产生的值,该值始终为None(因为 x = yield yields。)

In the second case, the parity of the calls is reversed. Now your first send does send to the x = yield line, so x gets set to 5. This send also yields the loop value in b, but you ignore this value in a and don't print it. You then print next(g), which is None. On each subsequent send, b prints the value of x, which is always 5 because that's what you always send, and then a prints the next yielded value, which is always None (because that's what x = yield yields).

通过yield语句在同一函数中接收和发送值并不能完全理解您的意思。您当然可以做到这一点,但是您必须意识到:a)即使调用 next(g),仍然会发送值(无); b)调用 g.send(5)时仍会产生一个值。

I don't quite get what you mean by "using the yield statement to both receive and send values in the same function". You can certainly do this, but you have to realize that: a) a value (None) is still sent even when you call next(g); and b) a value is still yielded when you call g.send(5).

这篇关于Python:我不明白这个生成器正在发生什么的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆