简体   繁体   English

python生成器中产量的确切返回点

[英]Exact return point of yield in python generators

In a quest to teach myself Python generators, especially their send() method, I wanted to write a toy example that would allow me calculate an "interruptible" Fibonacci sequence. 为了自学Python生成器,尤其是它们的send()方法,我想写一个玩具示例,让我计算一个“可中断的”斐波那契序列。

Eventually I succeeded, but I don't understand exactly what is going on. 最终我成功了,但是我不知道到底发生了什么。 Consider these two examples. 考虑这两个例子。

Successful example: 成功的例子:

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

Failure that I thought would work: 我认为可以解决的失败:

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'

Why does the second example not work? 为什么第二个示例不起作用? In particular, the second example seems assign a value of None to c in all but the first executions of the generator. 特别是,第二个示例似乎在生成器的第一次执行之外的所有其他操作中为c分配了None值。 Why? 为什么? How does it know to assign to c the first time next() is called, but not the next next() time? 如何知道第一次调用next()而不是下next()时分配给c

My understanding was that generators resume execution (when they are called again) beginning on the line after the yield line, but my example has me thinking this is wrong, at least in some cases. 我的理解是,生成器从屈服线之后的行开始恢复执行(当再次调用它们时),但是我的示例让我认为这是错误的,至少在某些情况下是这样。 Where exactly does execution resume from? 执行从何处恢复? Does it re-execute the yield line but this time with somehow leaving off everything after the yield ? 它会重新执行yield线,但是这次以某种方式放弃了yield后的所有内容吗? How does c get assigned to None ? c如何分配给None

yield is a bit of a strange expression. yield有点奇怪。 Execution pauses at the yield after the right-hand side is evaluated, but before the assignment takes place. 在评估右侧之后但在分配发生之前,执行会在yield处暂停。

The value that is returned in the yield statement is whatever you .send to the generator. yield语句中返回的值是您.send给生成器的任何.send Since you are calling .next rather than .send , the value returned from the yield expression ( c ) is None . 由于您正在调用.next而不是.send ,因此yield表达式( c )返回的值为None In the first example, that's fine since c is checked for truthiness and then is not used if it is falsy (eg None ). 在第一个示例中,这很好,因为会检查c的真实性,然后在它为假的情况下不使用它(例如None )。 However, in the second example, c isn't checked so you end up adding None to an integer (which obviously doesn't produce desirable results). 但是,在第二个示例中,未选中c因此最终将None添加到整数(这显然不会产生理想的结果)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM