5

是否可以嵌套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(最好是 even yield from x from yor yield from x for x in y,但这不是正确的语法)。为什么它没有按我的预期工作?

4

1 回答 1

7

yield是一个表达式,它会评估你的任何东西send(value)。简单地说,如果你什么都不发送,你会得到一个输出None,因为 的值为.yieldNone

yield from本身等于None,并且您正在使用其中的两个。在第二个yield from您正在迭代一个列表,该列表使用该列表的项目输入生成器,但您还yield from用于返回该生成器表达式,该表达式返回列表及其本身,这相当于None每次迭代,因此为什么在范围的每个项目迭代之后,您会得到一个None.

基本上这是正在发生的事情:

  1. (yield from y) for y in x产生值 [0, 1, 2]
  2. yield from产生前一个的值,也yield from产生前一个的值None
  3. 评估为 [0, 1, 2] ,然后添加一个None由于yield fromin (yield from y) for y in x

None不幸的是,由于表达式的性质,没有办法摆脱输出。你最好使用from_iterable.

解释收益率表达式的来源; https://docs.python.org/2.5/ref/yieldexpr.html

于 2017-04-13T07:34:12.100 回答