是否可以嵌套yield from
语句?
简单的形式很明显:
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
但是,我认为使用嵌套委托会更加pythonic(最好是yield from x from y
或yield from x for x in y
,但这不是正确的语法)。为什么它不像我期望的那样工作?
答案 0 :(得分:7)
yield
是一个表达式,它会评估你send(value)
的任何内容。简而言之,如果您不发送任何内容,那么您将获得None
输出,因为yield
的值为None
。
yield from
本身等于None
,您正在使用其中两个。在第二个yield from
,您将迭代一个列表,该列表使用该列表的项目输入生成器,但您还使用yield from
返回该生成器表达式,该表达式返回list和自身在每次迭代时相当于None
,因此为什么在每个项目迭代后你得到一个None
。
基本上这就是发生的事情:
(yield from y) for y in x
产生值[0,1,2] yield from
会产生之前的值,也会显示之前的yield from
None
。None
中添加yield from
(yield from y) for y in x
。不幸的是,由于表达式的性质,无法摆脱None
输出。您最好使用from_iterable
。