5

空でないシーケンスに対するイテレータは、フィルタリングも集計も行わず (sum()など)、何も生成しないのはなぜでしょうか?

簡単な例を考えてみましょう:

sequence = ['a', 'b', 'c']
list((el, ord(el)) for el in sequence)

これで期待通りの結果が得[('a', 97), ('b', 98), ('c', 99)]られます。

ord(el)ここで、 out を、いくつかのジェネレーターから最初の値を取得する式に交換するだけです(...).next()— 不自然な例を許してください:

def odd_integers_up_to_length(str):
    return (x for x in xrange(len(str)) if x%2==1)

list((el, odd_integers_up_to_length(el).next()) for el in sequence)

これにより が得られ[]ます。ええ、空のリストです。('a',スタッフ)タプルはありません。何もない。

ただし、フィルター処理、集計、削減は行っていません。nフィルタリングや集計を行わないオブジェクトに対するジェネレータ式は、オブジェクトを生成する必要がありnますよね? どうしたの?

4

4 に答える 4

13

odd_integers_up_to_length(el).next()そこではキャッチされませんが、その中のジェネレーター式でキャッチされ、何も生成せずに停止します。

値が「a」の場合の最初の反復を見てください。

>>> odd_integers_up_to_length('a').next()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration
于 2009-03-31T23:59:40.083 に答える
4

何が起こるかというと、next()呼び出しによってStopIteration例外が発生し、スタックが外側のジェネレーター式にバブルアップされ、その反復が停止します。

AStopIterationは、反復子が完了したことを通知する通常の方法です。通常、next()呼び出しはイテレータを消費するコンストラクト内で発生するため、通常は表示されfor x in iteratorませんsum(iterator)。しかし、next()直接呼び出す場合、StopIteration. そうしないと、抽象化でリークが発生し、外側の反復で予期しない動作が発生します。

教訓は、私が思うに: への直接呼び出しに注意することnext()です。

于 2009-04-01T00:01:30.220 に答える
0

str は予約済みのキーワードです。変数に別の名前を付ける必要があります

また、次のことについてアドバイスすることでした

于 2009-04-01T00:03:10.497 に答える
0
>>> seq=['a','b','c']
>>> list((el,4) for el in seq)
[('a',4), ('b',4), ('c',4)]

だから、listここであなたに迷惑をかけることはありません...

于 2009-04-01T00:04:53.097 に答える