如果您不使用收益率结果*,则可以 随时执行 以下操作:
yield from foo
…进入:
for bar in foo:
yield bar
可能会有性能成本**,但是从没有语义上的差异。
是否将两个半部分(上半部分和下半部分)中的条目彼此追加到一个列表中,以使父递归函数与call的收益并同时使用这两个半部分?
没有!迭代器和生成器的全部要点是,您无需构建实际的列表并将它们附加在一起。
但是 效果 是相似的:您只是从一种收益,然后从另一种收益。
如果您将上半部分和下半部分视为“懒惰列表”,那么可以,您可以将其视为“懒惰附加”,它会创建一个较大的“懒惰列表”。如果你调用list
父函数的结果,当然,你会 得到一个实际list
这相当于,如果你做这些,你会得到两个列表附加在一起yield list(…)
,而不是yield from …
。
但我认为反过来更容易想到:for
循环的作用与循环的作用完全相同。
如果将两个迭代器保存到变量中并进行循环itertools.chain(upper, lower)
,则与在第一个循环然后在第二个循环上进行相同,对吗?没什么区别。实际上,您可以实现chain
如下:
for arg in *args:
yield from arg
*不是生成器产生给调用者的值,而是生成器内部的yield表达式本身的值(使用send
方法从调用者产生),如PEP 342中所述。您没有在示例中使用这些。而且我敢打赌您不在您的真实代码中。但是协程风格的代码通常使用yield from
表达式的值-有关示例,请参阅PEP 3156。此类代码通常取决于Python 3.3生成器的其他功能-特别是StopIteration.value
来自引入了同一PEP 380的新功能yield from
—因此将不得不重写。但是,如果没有,您可以使用PEP来向您显示完整的,混乱的等价物,当然,您也可以减少不需要的部分。而且,如果您不使用表达式的值,它将缩减为上面的两行。
**数量不多,除了使用Python 3.3或完全重组代码外,您无能为力。这与将列表解析转换为Python 1.5循环完全相同,或者在XY版本中有新的优化并且您需要使用旧版本时,则为其他情况。