2017-04-13 8 views
5

yield from文をネストすることはできますか?なぜネスティングの "yield from"ステートメント(ジェネレータ委譲)が `None`値の終了を生成しますか?

シンプルな形は明白です:私は発電機を入れ子にしている

0 
1 
2 

しかし、どのような場合:生成

def try_yield1(): 
    x = range(3) 
    yield from x 

def try_yield_nested(): 
    x = [range(3) for _ in range(4)] 
    yield from ((yield from y) for y in x) 

これが生成します。

0 
1 
2 
None # why? 
0 
1 
2 
None # ... 
0 
1 
2 
None # ... 

私は(それが入れ子になっているにもかかわらず)yield fromを使用した場合、なぜそれがNoneを生成していますか?

私はのような何かを行うことができます知っている:(私が期待するものである)Noneを残し、同じ出力を生成し

from itertools import chain 

def try_yield_nested_alternative(): 
    x = [range(3) for _ in range(4)] 
    yield from chain.from_iterable(x) 

を。私はまた、単純なループ書き込むことができます。

for x in [range(3) for _ in range(3)]: 
    yield from x 

をしかし、私はネストされた委任を使用することがより神託のだろうと思った(好ましくさえyield from x from yまたはyield from x for x in yが、それは正しい構文ではありません)。なぜ私は期待どおりに動作していないのですか?

答えて

7

yieldは式で、あなたが何であれ評価しますsend(value)単純に言えば、何も送信しないとyieldの値がNoneになるため、Noneの出力が得られます。

yield fromNoneと同じですが、そのうち2つを使用しています。 2番目のyield fromではリストを反復していますが、そのリストの項目を使ってジェネレータを入力しますが、yield fromを使用してそのジェネレータの式を返します。これはリストを返すもので、各繰り返しでNoneに相当しますしたがって、各項目の反復の後、あなたはNoneになります。

本質的にこれが起こっていることである。

  1. (yield from y) for y in xは、[0、1 2]の値を、得
  2. yield fromは以前の値を生成し、またyield from前からNoneあります。
  3. [0,1,2]と評価し、次にyield fromのためにNoneを追加すると、(yield from y) for y in xになります。

残念ながら、式の性質上、Noneの出力を取り除く方法はありません。 from_iterableを使用する方がよいでしょう。収量表現を説明する出典; https://docs.python.org/2.5/ref/yieldexpr.html

関連する問題