你仍然需要循环。你在这里有递归并不重要。
您需要遍历递归调用产生的生成器并产生结果:
def foo(obj):
for ele in obj:
if isinstance(ele, list):
for res in foo(ele):
yield res
else:
yield ele
您的递归调用会生成一个生成器,您需要继续传递生成器的结果。您可以通过循环生成器并产生各个值来实现。
除了升级到 Python 3 之外,没有更好的选择。
yield from
本质上将循环的责任传递给调用者,并将任何generator.send()
和generator.throw()
调用传递回委托的生成器。你不需要传递.send()
or .throw()
,所以剩下的就是自己负责循环。
演示:
>>> import sys
>>> sys.version_info
sys.version_info(major=2, minor=7, micro=14, releaselevel='final', serial=0)
>>> def foo(obj):
... for ele in obj:
... if isinstance(ele, list):
... for res in foo(ele):
... yield res
... else:
... yield ele
...
>>> l = [1, [2, 3, [4,5]]]
>>> list(foo(l))
[1, 2, 3, 4, 5]
yield from
在PEP 380 --委托给子生成器的语法(不是 PEP 342)中引入,特别是因为子生成器上的循环不会委托generator.throw()
和generator.send()
信息。
PEP 明确指出:
如果产生值是唯一需要考虑的问题,则可以使用循环来轻松执行此操作,例如
for v in g:
yield v
Formal Semantics有一个 Python 实现等价物,一开始可能看起来很吓人,但您仍然可以选择它循环(使用while 1:
,当出现异常或处理时循环结束,使用orStopIteration
检索新值),并产生结果(与)。next()
generator.send(..)
yield _y