我在阅读这篇关于python中的async和await的article时,看到了以下示例代码:
def bottom():
# Returning the yield lets the value that goes up the call stack to come right back
# down.
return (yield 42)
def middle():
return (yield from bottom())
def top():
return (yield from middle())
# Get the generator.
gen = top()
value = next(gen)
print(value) # Prints '42'.
try:
value = gen.send(value * 2)
except StopIteration as exc:
value = exc.value
print(value) # Prints '84'.我可以理解返回42的链式生成器,但我似乎不能理解gen.send(value * 2)并返回84。我原以为最初的next(gen)已经在下面的实验中耗尽了生成器?
def bottom():
# Returning the yield lets the value that goes up the call stack to come right back
# down.
return (yield 42)
def middle():
return (yield from bottom())
def top():
return (yield from middle())
# Get the generator.
gen = top()
value = next(gen)
print(value) # Prints '42'.
value = next(gen)
print(value)
Traceback (most recent call last):
File "a.py", line 16, in <module>
value = next(gen)
StopIteration有没有人能解释一下?
附言:这不是一个经过深思熟虑的标题,请帮我修改一下……
发布于 2018-12-07 06:58:50
正如@Steven Rumbalski已经在评论中解释的那样:生成器只产生一个值- 42。在第二次调用中,迭代器引发被except __StopIteration__ as exc:捕获的StopIteration。所以你是完全正确的,因为初始的next(gen)已经耗尽了生成器。在您的第二个示例中也是如此,但是在本例中您没有捕获到StopIteration异常。为了进一步阅读,我将引用PEP380 --委派给子生成器的语法。
为生成器迭代器添加了一个新的send()方法,该方法恢复生成器并发送一个值,该值将成为当前yield expression表达式的结果。send()方法返回生成器生成的下一个值,或者如果生成器退出而没有生成其他值,则引发StopIteration。
来自PEP342
那么,为什么你在gen.send(value * 2)上又能得到84呢?此时,value的值仍然是上一次调用value = next(gen)时的42。所以你只是得到了你想要发送给迭代器的84。为什么会这样呢?
考虑以下简化的示例,以便更好地理解该定义的含义。首先,我们只产生一个值。没有退货。这将导致具有value属性None的空StopIteration。
def generator():
yield 1
gen = generator()
value = next(gen)
print(value) # Prints '1'.
try:
value = gen.send(3)
except StopIteration as exc:
value = exc.value
print(value) # Prints 'None'.生成器中的
return expr会导致在退出生成器时引发StopIteration(expr)。
来自PEP380
然后,我们在生成器不产生更多值后执行return 2。在这种情况下,来自PEP380的规则开始发挥作用。由于返回值为2,因此StopIteration的value属性为2。
def generator():
yield 1
return 2
gen = generator()
value = next(gen)
print(value) # Prints '1'.
try:
value = gen.send(3)
except StopIteration as exc:
value = exc.value
print(value) # Prints '2'.现在我们return (yield 1)。根据PEP342的规则,作为gen.send(3)的值的3将成为当前屈服表达式的结果。但是,由于生成器已经耗尽,因此会引发StopIteration异常。这导致3作为提升的StopIteration的value。
def generator():
return (yield 1)
gen = generator()
value = next(gen)
print(value) # Prints '1'.
try:
value = gen.send(3)
except StopIteration as exc:
value = exc.value
print(value) # Prints '3'.https://stackoverflow.com/questions/53659759
复制相似问题