私はこれを持っています:
>>> sum( i*i for i in xrange(5))
私の質問は、この場合、リスト内包表記またはジェネレーターオブジェクトを sum に渡すことですか? どうすればそれを伝えることができますか?これに関する一般的なルールはありますか?
また、 sum 自体には、その引数を囲むために一対の括弧が必要であることを覚えておいてください。上記の括弧は合計用であり、ジェネレーターオブジェクトを作成するためのものではないと思います。同意しませんか?
私はこれを持っています:
>>> sum( i*i for i in xrange(5))
私の質問は、この場合、リスト内包表記またはジェネレーターオブジェクトを sum に渡すことですか? どうすればそれを伝えることができますか?これに関する一般的なルールはありますか?
また、 sum 自体には、その引数を囲むために一対の括弧が必要であることを覚えておいてください。上記の括弧は合計用であり、ジェネレーターオブジェクトを作成するためのものではないと思います。同意しませんか?
ジェネレータ式を渡しています。
リスト内包表記は角括弧( )で指定します[...]
。リスト内包表記は最初にリスト オブジェクトを構築するため、リスト リテラル構文に密接に関連する構文を使用します。
list_literal = [1, 2, 3]
list_comprehension = [i for i in range(4) if i > 0]
一方、ジェネレータ式はイテレータ オブジェクトを作成します。そのオブジェクトを反復する場合にのみ、含まれているループが実行され、アイテムが生成されます。ジェネレータ式はそれらの項目を保持しません。作成中のリスト オブジェクトはありません。
ジェネレータ式は常に丸括弧を使用しますが、呼び出しの唯一(...)
の引数として使用する場合、括弧は省略できます。次の 2 つの式は同等です。
sum((i*i for i in xrange(5))) # with parenthesis
sum(i*i for i in xrange(5)) # without parenthesis around the generator
ジェネレータ式のドキュメントからの引用:
引数が 1 つだけの呼び出しでは、括弧を省略できます。詳細については、セクション呼び出しを参照してください。
リスト内包表記は で囲まれてい[]
ます:
>>> [i*i for i in xrange(5)] # list comprehension
[0, 1, 4, 9, 16]
>>> (i*i for i in xrange(5)) # generator
<generator object <genexpr> at 0x2cee40>
ジェネレーターを渡しています。
sum
また、「この構文は本当に一度に 1 つのアイテムをジェネレーターに消費させるのか、それともlist
最初にジェネレーター内のすべてのアイテムを秘密裏に作成するのか」と疑問に思うかもしれません。これを確認する 1 つの方法は、非常に広い範囲で試して、メモリ使用量を監視することです。
sum(i for i in xrange(int(1e8)))
この場合のメモリ使用量は一定で、asrange(int(1e8))
は完全なリストを作成し、数百 MB の RAM を消費します。
括弧がオプションであることをテストできます。
def print_it(obj):
print obj
print_it(i for i in xrange(5))
# prints <generator object <genexpr> at 0x03853C60>
私はこれを試しました:
#!/usr/bin/env python
class myclass:
def __init__(self,arg):
self.p = arg
print type(self.p)
print self.p
if __name__ == '__main__':
c = myclass(i*i for i in xrange(5))
そして、これは次のように出力されます:
$ ./genexprorlistcomp.py
<type 'generator'>
<generator object <genexpr> at 0x7f5344c7cf00>
これは、Martin と mdscruggs が投稿で説明した内容と一致しています。
ジェネレーター オブジェクトを渡しています。リスト内包表記は で囲まれてい[]
ます。