web-dev-qa-db-ja.com

ネストされたジェネレーター関数から結果を生成する方法は?

ダウンロードして結果を出す機能があります。この質問の目的のために、毎秒1回スティングを生成するが、ジェネレーターをラップする便利な関数が欲しいとしましょう:

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>

どうすれば通常のジェネレーター関数のように文字列を生成できますか?

47
Jon Cage

これを逃したなんて信じられません。答えは、適切な引数が適用されたジェネレーター関数を単に返すことです。

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
25
Jon Cage

new yield from 、Python 3.3以降、「 委任ジェネレーター 」として知られている)から利用可能。

質問が正しく理解できれば、同じ問題に出くわし、別の場所で答えを見つけました。

私はこのようなことをしたかった:

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:ジェネレーターで「yield from」を使用する-Part 1(simeonvisser.com)

20
Hibou57

「ネストされた収量」の異なる形式を探してここに来て、最終的に隠された答えを見つけました。最高ではないかもしれませんが、それは機能します。

レジストリツリーを介して譲りたかったのですが、これが解決策です。

        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
2
ben

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()
1
displayname

ネストされた利回りの別の使用法を探しに来ました。

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]
1
Ben