为什么嵌套“yield from”语句(生成器代理)会生成终止`None`值?
问题描述:
是否可以嵌套yield from
陈述?为什么嵌套“yield from”语句(生成器代理)会生成终止`None`值?
简单形式是显而易见的:
def try_yield1():
x = range(3)
yield from x
主要生产:
0
1
2
但如果我有嵌套发电机?
def try_yield_nested():
x = [range(3) for _ in range(4)]
yield from ((yield from y) for y in x)
这将产生:
0
1
2
None # why?
0
1
2
None # ...
0
1
2
None # ...
为什么会产生None
,如果我用yield from
(即使它是嵌套的)?
我知道我可以这样做:
from itertools import chain
def try_yield_nested_alternative():
x = [range(3) for _ in range(4)]
yield from chain.from_iterable(x)
其中产生相同的输出,保留了None
(这是我期望的那样)。我也可以写一个简单的循环:
for x in [range(3) for _ in range(3)]:
yield from x
但是,我认为这将是更Python使用嵌套代表团(最好连yield from x from y
或yield from x for x in y
,但这不是正确的语法)。为什么它不像我预期的那样工作?
答
yield
是一个表达式,它会评估你的任何你send(value)
它。简而言之,如果您不发送任何内容,您将获得None
输出,因为yield
的值将为None
。
yield from
本身等于None
,并且您正在使用其中两个。在第二个yield from
中,您正在迭代一个列表,它将生成器与该列表中的项目一起输入,但是您还使用yield from
来返回该生成器表达式,该表达式返回列表,并且它自身也会在每次迭代时返回None
,那么为什么在每次迭代范围后,你会得到一个None
。
本质上讲,这是正在发生的事情:
-
(yield from y) for y in x
得到的值,[0,1,2] -
yield from
从先前产生的值,并且还从yield from
以前这是None
。 - 评估为[0,1,2],然后在
(yield from y) for y in x
中添加由于yield from
而产生的None
。
不幸的是,由于表达式的性质,没有办法摆脱None
输出。你最好用from_iterable
。