あなたはいくつかのことを混ぜ合わせています。
def list_gen(n):
i=0
while i<n:
yield i
i += 1
この関数はジェネレータです。これを呼び出すと、イテレータであるジェネレータオブジェクトが返されます。
イテレータは、を持っているものですnext()
。つまり、一度トラバースすることができます。イテレータはiter
、を実行するたびにを使用して何かの上に作成されますfor i in something
。
def list_gen(n):
return range(n)
def list_gen(n):
return xrange(n)
これらの関数は通常の関数です。1つはaを返し、もう1つはオブジェクトlist
を返しxrange
ます。リストとxrangeはどちらも反復可能です。つまり、複数の独立した反復子を作成できます。
質問に戻りましょう。あなたは、オブジェクトを返すかオブジェクトを返すかを尋ねてlist
いxrange
ます。
それは明らかに依存します!それはあなたが結果で何をしたいかによります。
どういうわけかそれを変更したい場合は、実際のリストが必要です。range
直接使用してください。
それだけを繰り返したい場合は、意味的には違いはありません。xrange
オブジェクトとlist
によって返されるbyの両方range
が、同じシーケンスを繰り返すイテレーターを生成します。
ただし、を使用するxrange
と、リスト全体がメモリに作成されることはありません。list
単純な反復だけを実行したいのに、なぜ本格的なオブジェクトをメモリに作成するのでしょうか。for
ループが必要なときはいつでも、一時的に大きなメモリバッファを割り当てる必要はありませんよね?
したがってxrange
、発信者はいつでもlist
それを利用できるため、に固執するのは安全です。
ベンチマークで確認しましょう。によって構築されたリストよりもxrangeを反復処理する方が速いかどうかを知りたいです(もちろん、呼び出しrange
のコストを含みます)。range
コード:
import timeit
ns = [1,2,3, 5, 10, 50, 100]
print 'n', '\t', 'range', '\t', 'xrange'
for n in ns:
t1 = timeit.timeit("for i in range({}): pass".format(n))
t2 = timeit.timeit("for i in xrange({}): pass".format(n))
print n, '\t', t1, '\t', t2
結果:
n range xrange
1 0.566222990493 0.418698436395
2 0.594136874362 0.477882061758
3 0.630704800817 0.488603362929
5 0.725149288913 0.540597548519
10 0.90297752809 0.687031507818
50 2.44493085566 1.89102105759
100 4.31189321914 3.33713522433