2017-07-19 51 views
5

阅读有关Python协程,我遇到了这个代码:为什么这个Python生成器/协程失去一个值?

def countdown(n): 
    print("Start from {}".format(n)) 
    while n >= 0: 
     print("Yielding {}".format(n)) 
     newv = yield n 
     if newv is not None: 
      n = newv 
     else: 
      n -= 1 

c = countdown(5) 
for n in c: 
    print(n) 
    if n == 5: c.send(2) 

这奇怪的输出:

Start from 5 
Yielding 5 
5 
Yielding 3 
Yielding 2 
2 
Yielding 1 
1 
Yielding 0 
0 

特别是,它错过打印3。为什么?


,因为我不要求什么send确实引用的问题不回答这个问题。它将值发送回函数。我问的是为什么在我发行send(3)后,下一个产量应该是3,不会导致for循环打印3.

+0

首先,它也错过了4。其次,你认为'c.send(3)'做了什么? – alfasin

+0

@alfasin由于'c.send(3)',它错过了4。关键是代码应该将'n'设置为3,然后在下一个循环中产生3.但是它不会被打印。为什么? – Ritzymon

+0

如果你在'if newv不是None:'block –

回答

4

您从未检查过您的c.send(3)调用的返回值。 事实上,看起来send方法本身提前发生器, ,所以你的失踪3yield在那c.send(3)调用。

def countdown(n): 
    while n >= 0: 
     newv = yield n 
     if newv is not None: 
      n = newv 
     else: 
      n -= 1 

c = countdown(5) 
print(next(c)) 
print(c.send(3)) 
print(next(c)) 

输出将是:

5 
3 
2 

它实际上是documented

generator.send(值)

恢复执行和“发送”的值进发电机功能。 value参数成为当前产出表达式的结果。 的send()方法返回下一个值由发电机产生,或提高 StopIteration异常如果发电机退出而不产生另一个 值。

0

您在c.send()中失败。你比较当n == 5,但你没有发送5(在你的功能是n-1),你发送3.例如,它不打印4.

尝试相同的代码,但与c.send(5),它将从5打印到0.

c = countdown(5) 
for n in c: 
    print(n) 
    if n == 5: c.send(5) 
+0

中加入'print('newv:{}'。format(newv)',它就变得更清晰了。实际上,它不会从5打印到0。 5','3','2','1','0',缺少'4'。同样的问题。 – Ritzymon

相关问题