【问题标题】:Python generator to yield everything from another generator callPython 生成器从另一个生成器调用中产生所有内容
【发布时间】:2011-09-09 14:26:32
【问题描述】:

我有一个 Python 生成器,它可以调用自身来获取更多要生成的元素。它看起来像这样:

def gen(list):
    # ...
    if list:
        for x in gen(list[1:]):
            yield x

我的问题是关于最后两行:有没有更简洁的方式来表达这一点?我希望有这样的东西(理解这不是有效的 Python):

def gen(list):
    # ...
    if list:
        yield each in gen(list[1:])

【问题讨论】:

  • 我不太明白这应该做什么,我最初认为这只是将列表转换为生成器的一种天真的方式,但我错了。你能启发我吗?
  • 如果我错了,请纠正我,但该代码看起来总是会返回一个空列表。我认为评论中必须有其他收益?
  • @Dunes: 是的,评论中还有其他收益。
  • @Davy8:它不是包装器或转换器,它是我编写的自定义生成器。它接受一个事物列表并生成另一个列表,该列表可能包含一些相同的事物,也可能不包含。一种“过滤器”。

标签: python recursion generator yield


【解决方案1】:

Python 3.3 added the yield from keyword。这是您当前拥有的代码与使用 new 关键字的代码之间的比较:

yield_from_test.py:

def gen_for(a_list):
    if a_list:
        yield a_list[0]
        for x in gen_for(a_list[1:]):
            yield x

def gen_yield(a_list):
    if a_list:
        yield a_list[0]
        yield from gen_yield(a_list[1:])

if __name__ == '__main__':
    assert list(gen_for([1,2,3])) == list(gen_yield([1,2,3]))
    print(list(gen_yield([1,2,3])))

» python3 yield_from_test.py [1, 2, 3]

【讨论】:

    【解决方案2】:

    有人要求yield from 或类似的“传递”子生成器返回的所有值。请参阅PEP 380 了解一些已被反弹的想法。但是,尚未实施任何事情。你的第一个例子是正确的。

    【讨论】:

    • 注意:Python 3.3 和 PEP 380 (yield from) 已经发布。
    【解决方案3】:

    您的代码示例非常惯用和简洁,不需要也没有真正的机会进行进一步改进,尤其是在可读性方面。

    【讨论】:

    • 节点生成器有a syntax 用于将生成委托给另一个生成器:yield* my_generator(...)。我个人觉得这样更简洁。随着 PEP 和采用,事情变得惯用......
    【解决方案4】:

    您的第一个示例是正确的解决方案。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-11-23
      • 2014-09-17
      • 2018-12-11
      • 1970-01-01
      • 2018-07-29
      • 2020-10-10
      • 2018-06-22
      相关资源
      最近更新 更多