python - 为什么嵌套 "yield from"语句(生成器委托(delegate))会产生终止值 `None`?

标签 python python-3.x generator yield yield-from

是否可以嵌套 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 # ...

如果我使用 yield from 为什么会生成 None(即使它是嵌套的)?

我知道我可以做类似的事情:

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

但是,我认为使用嵌套委托(delegate)会更符合 pythonic(最好是 yield from x from yyield from x for x in y,但这是语法不正确)。为什么它没有像我预期的那样工作?

最佳答案

yield 是一个表达式,它会评估您发送(值) 的任何内容。简而言之,如果您什么都不发送,您将得到一个 None 输出,因为 yield 的值将是 None

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 from in (yield from y) for y in x.

不幸的是,由于表达式的性质,无法摆脱 None 输出。您最好使用 from_iterable

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

关于python - 为什么嵌套 "yield from"语句(生成器委托(delegate))会产生终止值 `None`?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43385115/

相关文章:

python - 将 ndarray(OpenCV 中的图像)作为 .jpg 或 .png 上传到谷歌云存储

python - python Tkinter,线程和循环

python - 将文件读入列表并去除换行符

python - 从单词列表中查找字符出现百分比

python - 生成器函数性能

python - 为什么在使用 concurrent.futures.ProcessPoolExecuter() 进行多处理期间不止一次打印此消息?

python - 无法导入已安装的模块(通过 pip)

python - 将嵌套字典中的键和值从列表格式获取到数据帧中

javascript - 如何使用作为生成器并能够链接它们的函数来扩展数组?

javascript - 如何对 ES6 生成器进行特征检测?