[英]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.
考虑这两个例子。
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'
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.