【问题标题】:How to yield results from a nested generator function?如何从嵌套生成器函数中产生结果?
【发布时间】:2012-06-27 04:07:36
【问题描述】:

我有一个函数可以在下载结果时产生结果。出于这个问题的目的,假设我每秒产生一次刺痛,但我想要一个方便的函数来包装我的生成器:

import time

def GeneratorFunction(max_val):
    for i in range(0,5):
        time.sleep(1)
        yield "String %d"%i

def SmallGenerator():
    yield GeneratorFunction(3)

for s in SmallGenerator():
    print s

...为什么不只打印我期望的 5 个字符串?相反,它似乎返回了生成器函数:

<generator object GeneratorFunction at 0x020649B8>

我怎样才能让它像普通的生成器函数那样产生字符串?

【问题讨论】:

  • 仅供参考,在 Python 3.3 中,yield from GeneratorFunction(3) 可以工作..
  • @DSM:谢谢。还没有完全过渡到 3+...

标签: python function nested generator yield


【解决方案1】:

不敢相信我错过了这个;答案是简单地返回应用了合适参数的生成器函数:

import time

def GeneratorFunction(max_val):
    for i in range(0,max_val):
        time.sleep(1)
        yield "String %d"%i

def SmallGenerator():
    return GeneratorFunction(3) # <-- note the use of return instead of yield

for s in SmallGenerator():
    print s

【讨论】:

  • 除非你的函数是:yield GeneratorFunction(3) yield GeneratorFunction(2)。在这种情况下,退货将不起作用。 Yield From 满足此要求。
  • 但是如果你在def SmallGenerator():里面使用return,它就不再是一个嵌套的生成器函数了??还是它??
【解决方案2】:

您可能必须使用自 Python 3.3 起可用的new yield from,称为“delegated generator”。

如果我正确理解了这个问题,我会遇到同样的问题,并在其他地方找到了答案。

我想做这样的事情:

def f():

    def g():

        do_something()
        yield x
        …
        yield y

    do_some_other_thing()
    yield a
    …
    g()  # Was not working.
    yield g()  # Was not what was expected neither; yielded None.
    …
    yield b

我现在改用这个:

yield from g()  # Now it works, it yields x and Y.

我从这个页面得到了答案:Python 3: Using "yield from" in Generators - Part 1 (simeonvisser.com)

【讨论】:

    【解决方案3】:

    来到这里寻找另一种形式的“嵌套收益”,终于找到了隐藏的答案。可能不是最好的,但它确实有效。

    我想通过注册表树来让步,这就是解决方案。

            def genKeys(key):
                for value in key.values():
                    yield value
                for subkey in key.subkeys():
                    print(subkey)
                    for x in genKeys(subkey): #this is the trick
                        continue
    

    【讨论】:

    • 看起来这会产生顶级值,并递归地打印子键,但不会递归地产生任何东西。还是我错过了什么?
    【解决方案4】:

    这是另一个生成从 1 到 10 的乘法表的小例子:

    class Gen1:
    
        def __init__(self, gen2):
            self.gen2 = gen2
    
        def __iter__(self):    
            for a in range(1, 11):    
                for b in self.gen2:
                    yield a * b
    
    
    class Gen2:    
    
        def __iter__(self):
            for a in range(1, 11):
                yield a
    
    
    def main():
    
        gen2 = Gen2()
        gen1 = Gen1(gen2)
    
        for v in gen1:
            print(v)
    
    if __name__ == '__main__':
        main()
    

    【讨论】:

      【解决方案5】:

      我来寻找嵌套收益的另一种用途..

      list_of_lists = [
          [1, 2, 3],
          [4, 5, 6],
          [7, 8, 9],
      ]
      
      def iter_all(foo):
          yield foo
      
          if isinstance(foo, list):
              for i in foo:
                  for x in iter_all(i):
                      yield x
      
      
      print([i for i in iter_all(list_of_lists)])
      

      输出:

      [[[1, 2, 3], [4, 5, 6], [7, 8, 9]], [1, 2, 3], 1, 2, 3, [4, 5, 6], 4, 5, 6, [7, 8, 9], 7, 8, 9]
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-04-14
        • 1970-01-01
        • 2011-02-03
        • 2017-03-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多