web-dev-qa-db-ja.com

Pythonで2つの連続したyieldステートメントはどのように機能しますか?

マージと分割のセクションで pymotw.com からこのコードを見つけました。

from itertools import *


def make_iterables_to_chain():
    yield [1, 2, 3]
    yield ['a', 'b', 'c']


for i in chain.from_iterable(make_iterables_to_chain()):
    print(i, end=' ')
print()

Make_iterables_to_chain()がどのように機能しているか理解できません。 2つの収量ステートメントが含まれていますが、どのように機能しますか?私は発電機がどのように機能するかを知っていますが、そこには1つしかありませんでした 産出 ステートメント。

助けてください!

11
unnobtainium

単一のyieldが機能するのと同じ方法。

ジェネレーターには、yieldをいくつでも含めることができます。__next__が呼び出されると、次の収量にぶつかるまで実行されます。次に、生成された式を取得し、__next__メソッドが再度呼び出されるまでジェネレーターが一時停止します。

ジェネレーターでnext呼び出しをいくつか実行して、これを確認します。

>>> g = make_iterables_to_chain()  # get generator
>>> next(g) # start generator, go to first yield, get result
[1, 2, 3]
>>> next(g) # resume generator, go to second yield, get result
['a', 'b', 'c']
>>> # next(g) raises Exception since no more yields are found 

ジェネレーターは、事実上、関数が複数回を返すことを許可します。 yieldステートメントが実行されるたびに、値が呼び出し元に返され、呼び出し元は関数の実行を継続できます。

通常、これらはforループで反復可能オブジェクトとして使用されます。

次の関数は、イテラブル内のすべての要素を量だけ増分します。

def inc_each(nums, inc):
    for i in nums:
        yield i + inc

次に使用例を示します。

gen = inc_each([1, 2, 3, 4], 100)
print(list(gen)) # [101, 102, 103, 104]

listは、任意のイテラブル(この場合はジェネレーター)をリストに変換するために使用されます。

説明する関数は、2つのyieldステートメントを実行します。

def make_iterables_to_chain():
    yield [1, 2, 3]
    yield ['a', 'b', 'c']

これを呼び出すと、ジェネレーターが返され、反復処理されると、リスト[1, 2, 3]および['a', 'b', 'c']が生成されます。

gen = make_iterables_to_chain()
print(list(gen)) # [[1, 2, 3], ['a', 'b', 'c']]

itertools.chain.from_iterableは、(無限の可能性がある)反復可能な反復可能オブジェクトを取得して「フラット化」し、結果として(無限の可能性がある)反復可能を返します。

実装方法は次のとおりです。

def from_iterable(iterables):
    for iterable in iterables:
        for i in iterable:
            yield i
0
Challenger5