首页 文章

'yield from'在Python 2中替代

提问于
浏览
0

我的代码在 recursive callspython3 中使用了yield from,它完全正常 . 现在的问题是,这是从_797334_ python 3.3中引入的,我需要它在python 2.7中工作 . 我读了几篇文章,其中没有一篇足够详细或简单 .

很少提到文章:

还有其他人 .

我已经重新创建了一个小的示例代码(它接受一个多级列表并返回一个扁平列表),这与我的要求相比是 very minimalistic .

#python 3
def foo(obj):
    for ele in obj:
        if isinstance(ele, list):
            yield from foo(ele)
        else:
            yield ele

#driver值:

>>> l = [1, [2, 3, [4,5]]]
>>> list(foo(l))
=>  [1, 2, 3, 4, 5]

由于 yield from 不可用,转换后的相同内容在 python 2.7 中不起作用 .

2 回答

  • 3

    still need to loop . 你在这里递归并不重要 .

    您需要遍历由递归调用生成的生成器并生成结果:

    def foo(obj):
        for ele in obj:
            if isinstance(ele, list):
                for res in foo(ele):
                    yield res
            else:
                yield ele
    

    您的递归调用会生成一个生成器,您需要向前传递生成器的结果 . 您可以通过循环生成器并生成各个值来实现 .

    There are no better options ,不是升级到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明确指出:

    如果值的产生是唯一的问题,那么使用循环(例如对于v in g)可以毫不费力地执行:
    产量v

    Formal Semantics有一个Python实现等效,起初可能看起来令人生畏,但你仍然可以选择它循环(使用 while 1: ,当存在异常或 StopIteration 被处理时,循环结束,使用 next()generator.send(..) 检索新值),以及产生结果(使用 yield _y ) .

  • 1

    为什么你说“我的代码无法使用循环并需要递归”?您可以在递归生成器中轻松使用循环:

    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))
    

    output

    [1, 2, 3, 4, 5]
    

相关问题