'yield from' 替换为 Python 2
'yield from' substitute in Python 2
我的代码使用 yield from
in python3
in recursive calls and it works perfectly fine. The problem right now is that this was introduced from PEP-380 in python 3.3
and I need it to work in python 2.7
。我阅读了几篇文章,其中 none 足够详细或足够简单。
几篇参考文章:
Converting “yield from” statement to Python 2.7 code
和其他一些人。
我重新创建了一个小示例代码 (它采用多级列表和 returns 扁平化列表) 即 与我的要求相比,非常简约。
#python 3
def foo(obj):
for ele in obj:
if isinstance(ele, list):
yield from foo(ele)
else:
yield ele
#驱动值:
>>> l = [1, [2, 3, [4,5]]]
>>> list(foo(l))
=> [1, 2, 3, 4, 5]
由于 yield from
不可用,相同的转换在 python 2.7
中不起作用。
你还需要循环。你在这里递归并不重要。
您需要遍历递归调用生成的生成器并产生结果:
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()
或 .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 -- Syntax for Delegating to a Subgenerator(不是 PEP 342)中引入的,特别是因为子生成器上的循环不会委托 generator.throw()
和 generator.send()
信息。
PEP 明确指出:
If yielding of values is the only concern, this can be performed without much difficulty using a loop such as
for v in g:
yield v
Formal Semantics 有一个 Python 实现等价物,乍一看可能令人生畏,但您仍然可以看出它 循环 (使用 while 1:
,当出现异常或StopIteration
被处理时循环结束,用next()
或generator.send(..)
检索新值,并产生结果(用yield _y
) .
为什么说"my code cannot work with loops and needs to be recursive"?您可以轻松地在递归生成器中使用循环:
def foo(obj):
for ele in obj:
if isinstance(ele, list):
#yield from foo(ele)
for t in foo(ele):
yield t
else:
yield ele
l = [1, [2, 3, [4, 5]]]
print list(foo(l))
输出
[1, 2, 3, 4, 5]
我的代码使用 yield from
in python3
in recursive calls and it works perfectly fine. The problem right now is that this was introduced from PEP-380 in python 3.3
and I need it to work in python 2.7
。我阅读了几篇文章,其中 none 足够详细或足够简单。
几篇参考文章:
Converting “yield from” statement to Python 2.7 code
和其他一些人。
我重新创建了一个小示例代码 (它采用多级列表和 returns 扁平化列表) 即 与我的要求相比,非常简约。
#python 3
def foo(obj):
for ele in obj:
if isinstance(ele, list):
yield from foo(ele)
else:
yield ele
#驱动值:
>>> l = [1, [2, 3, [4,5]]]
>>> list(foo(l))
=> [1, 2, 3, 4, 5]
由于 yield from
不可用,相同的转换在 python 2.7
中不起作用。
你还需要循环。你在这里递归并不重要。
您需要遍历递归调用生成的生成器并产生结果:
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()
或 .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 -- Syntax for Delegating to a Subgenerator(不是 PEP 342)中引入的,特别是因为子生成器上的循环不会委托 generator.throw()
和 generator.send()
信息。
PEP 明确指出:
If yielding of values is the only concern, this can be performed without much difficulty using a loop such as
for v in g: yield v
Formal Semantics 有一个 Python 实现等价物,乍一看可能令人生畏,但您仍然可以看出它 循环 (使用 while 1:
,当出现异常或StopIteration
被处理时循环结束,用next()
或generator.send(..)
检索新值,并产生结果(用yield _y
) .
为什么说"my code cannot work with loops and needs to be recursive"?您可以轻松地在递归生成器中使用循环:
def foo(obj):
for ele in obj:
if isinstance(ele, list):
#yield from foo(ele)
for t in foo(ele):
yield t
else:
yield ele
l = [1, [2, 3, [4, 5]]]
print list(foo(l))
输出
[1, 2, 3, 4, 5]