これはジェネレータ式です。スタンドアロンの場合に動作させるには、中括弧を使用します。
y = (x for x in range(10))
y はジェネレータになります。ジェネレーターを反復できるため、関数など、反復可能が期待される場所でsum
機能します。
使用例と落とし穴:
>>> y = (x for x in range(10))
>>> y
<generator object <genexpr> at 0x0000000001E15A20>
>>> sum(y)
45
ジェネレーターを保持するときは注意してください。それらを通過できるのは 1 回だけです。したがって、上記の後にsum
再度使用しようとすると、次のようになります。
>>> sum(y)
0
そのため、実際にリストやセット、または同様のものが期待されるジェネレーターを渡す場合は、注意が必要です。関数またはクラスが引数を格納し、それを複数回反復しようとすると、問題が発生します。たとえば、次のように考えてください。
def foo(numbers):
s = sum(numbers)
p = reduce(lambda x,y: x*y, numbers, 1)
print "The sum is:", s, "and the product:", p
ジェネレーターを渡すと失敗します。
>>> foo(x for x in range(1, 10))
The sum is: 45 and the product: 1
ジェネレーターが生成する値から簡単にリストを取得できます。
>>> y = (x for x in range(10))
>>> list(y)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
これを使用して、前の例を修正できます。
>>> foo(list(x for x in range(1, 10)))
The sum is: 45 and the product: 362880
ただし、ジェネレーターからリストを作成する場合は、すべての値を保存する必要があることに注意してください。これは、アイテムがたくさんある状況では、より多くのメモリを使用する可能性があります。
あなたの状況でジェネレーターを使用する理由は何ですか?
sum(generator expression)
がより優れている理由は、メモリ消費量がはるかに少ないことsum(list)
です。ジェネレーター バージョンは単一の値のみを格納する必要がありますが、リスト バリアントは N 個の値を格納する必要があります。したがって、副作用の危険がないジェネレーターを常に使用する必要があります。