3 回答
TA贡献1843条经验 获得超7个赞
如果您不使用收益率*,则可以随时将其转换为:
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版本中进行了新的优化并且您需要使用旧版本时,则与其他情况完全相同。
TA贡献1775条经验 获得超11个赞
我只是碰到这个问题,我使用的是一个有点困难,因为我需要返回值的yield from:
result = yield from other_gen()
不能将其表示为简单的for循环,但可以用以下方式重现:
_iter = iter(other_gen())
try:
while True: #broken by StopIteration
yield next(_iter)
except StopIteration as e:
if e.args:
result = e.args[0]
else:
result = None
希望这将帮助遇到相同问题的人们。:)
TA贡献1794条经验 获得超7个赞
用for循环替换它们:
yield from range(L[start] + 1, L[end])
==>
for i in range(L[start] + 1, L[end]):
yield i
关于元素也是如此:
yield from missing_elements(L, index, end)
==>
for el in missing_elements(L, index, end):
添加回答
举报