python 台发电机的精确 return 产量点

Exact return point of yield in python generators

为了自学 Python 生成器,尤其是他们的 send() 方法,我想编写一个玩具示例来计算 "interruptible" 斐波那契数列。

最后我成功了,但我不明白到底是怎么回事。考虑这两个例子。

成功范例:

def genFib(a=0, b=1):
    while True:
        c = yield a+b
        if c:
            a, b = b, c
        else:
            a, b = b, a+b
    return
​
fib_number = genFib()
​
print fib_number.next()
print fib_number.next()
print fib_number.next()
print fib_number.next()
print fib_number.next()
print fib_number.send(100)
print fib_number.next()
print fib_number.next()
​
1
2
3
5
8
105
205
310

我认为可行的失败:

def genFib(a=0, b=1):
    while True:
        c = yield a+b
        a, b = b, c
    return
​
fib_number = genFib()
​
print fib_number.next()
print fib_number.next()
1
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-59-4513153ea517> in <module>()
      8 
      9 print fib_number.next()
---> 10 print fib_number.next()

<ipython-input-59-4513153ea517> in genFib(a, b)
      1 def genFib(a=0, b=1):
      2     while True:
----> 3         c = yield a+b
      4         a, b = b, c
      5     return

TypeError: unsupported operand type(s) for +: 'int' and 'NoneType'

为什么第二个示例不起作用? 特别是,第二个示例似乎在所有 [=36] 中将 None 的值分配给 c =]但是生成器的第一个次执行。为什么?它如何知道在第一次调用 next() 时分配给 c,而不是下一次 next() 时间?

我的理解是生成器恢复执行(当它们被再次调用时)从 yield 线 之后 行开始,但我的例子让我认为这是错误的,至少在某些情况下。执行从哪里恢复?它是否重新执行 yield 行,但这次以某种方式在 yield 之后删除了所有内容? c 如何分配给 None

yield 有点奇怪。在计算右侧之后但在赋值发生之前,执行在 yield 处暂停。

yield 语句中返回的值是您 .send 生成器的任何值。由于您调用的是 .next 而不是 .send,因此从 yield 表达式 (c) 返回的值是 None。在第一个示例中,这很好,因为检查了 c 的真实性,如果它是假的则不使用(例如 None)。但是,在第二个示例中,未检查 c,因此您最终将 None 添加到一个整数(这显然不会产生理想的结果)。