回答:
Python 2.xの場合:
range
リストを作成するので、これを行うrange(1, 10000000)
と、9999999
要素を含むメモリ内にリストが作成されます。
xrange
遅延評価されるシーケンスオブジェクトです。
Python 3では、Python range
のと同等のものをxrange
実行しますlist(range(...))
。リストを取得するには、を使用する必要があります。
xrange(x).__iter__()
ジェネレーターです。
i
が初期化ではなくオンデマンドで評価されることを意味します。
rangeはリストを作成するので、これを行う
range(1, 10000000)
と、9999999
要素を含むリストがメモリ内に作成されます。
xrange
はジェネレーターであるため、遅延評価されるシーケンスオブジェクトです。
これは事実ですが、Python 3では.range()
Python 2によって実装され.xrange()
ます。実際にリストを生成する必要がある場合は、次のことを行う必要があります。
list(range(1,100))
timeit
モジュールを使用して、コードの小さなスニペットのどれが速いかをテストしてください!
$ python -m timeit 'for i in range(1000000):' ' pass'
10 loops, best of 3: 90.5 msec per loop
$ python -m timeit 'for i in xrange(1000000):' ' pass'
10 loops, best of 3: 51.1 msec per loop
個人的には、本当に大量のリスト.range()
を扱っているのでない限り、私は常にを使用します-ご覧のとおり、100万のエントリのリストの場合、追加のオーバーヘッドはわずか0.04秒です。そして、Coreyが指摘しているように、Python 3.0 は廃止され、とにかく素晴らしいイテレータ動作を提供します。.xrange()
.range()
python -m timeit "for i in xrange(1000000):" " pass"
the extra overhead is only 0.04 seconds
それを見る正しい方法ではありません。(90.5-51.1)/51.1 = 1.771 times slower
これがプログラムのコアループである場合、それがボトルネックになる可能性があることを伝えるためです。ただし、これが小さな部分である場合、1.77xはそれほど多くありません。
xrange
範囲パラメータのみを保存し、オンデマンドで数値を生成します。ただし、PythonのC実装は現在、その引数をC longに制限しています。
xrange(2**32-1, 2**32+1) # When long is 32 bits, OverflowError: Python int too large to convert to C long
range(2**32-1, 2**32+1) # OK --> [4294967295L, 4294967296L]
Python 3.0 range
では、2.xと同じように動作xrange
しますが、最小エンドポイントと最大エンドポイントの制限はありません。
xrangeはイテレータを返し、一度に1つの数値のみをメモリに保持します。rangeは、数値のリスト全体をメモリに保持します。
xrange
イテレータを返しません。
and only keeps one number in memory at a time
残りが配置される場所と私を導いてください...
Library Referenceを少し時間をかけてください。それに慣れれば読むほど、このような質問に対する回答をすばやく見つけることができます。特に重要なのは、組み込みオブジェクトと型に関する最初のいくつかの章です。
xrangeタイプの利点は、xrangeオブジェクトは、それが表す範囲のサイズに関係なく、常に同じ量のメモリを使用することです。一貫したパフォーマンス上の利点はありません。
Pythonコンストラクトに関する簡単な情報を見つけるもう1つの方法は、docstringとhelp-functionです。
print xrange.__doc__ # def doc(x): print x.__doc__ is super useful
help(xrange)
私は誰もドキュメントを読んでいないことにショックを受けています:
この関数はによく似て
range()
いますxrange
が、リストではなくオブジェクトを返します。これは不透明なシーケンスタイプであり、対応するリストと同じ値を生成しますが、実際にすべてを同時に保存することはありません。非常に大きな範囲がメモリ不足のマシンで使用されている場合、または範囲のすべての要素が使用されていない場合(ループが使用されている場合など)を除いて、xrange()
オーバーの利点range()
は最小限です(xrange()
要求されたときに値を作成する必要があるため)。通常はbreak
)で終了します。
あなたはの利点でしょうxrange
オーバーをrange
この単純な例では:
import timeit
t1 = timeit.default_timer()
a = 0
for i in xrange(1, 100000000):
pass
t2 = timeit.default_timer()
print "time taken: ", (t2-t1) # 4.49153590202 seconds
t1 = timeit.default_timer()
a = 0
for i in range(1, 100000000):
pass
t2 = timeit.default_timer()
print "time taken: ", (t2-t1) # 7.04547905922 seconds
上記の例は、の場合、大幅に優れたものを反映していませんxrange
。
次にrange
、と比較して本当に遅い次のケースを見てくださいxrange
。
import timeit
t1 = timeit.default_timer()
a = 0
for i in xrange(1, 100000000):
if i == 10000:
break
t2 = timeit.default_timer()
print "time taken: ", (t2-t1) # 0.000764846801758 seconds
t1 = timeit.default_timer()
a = 0
for i in range(1, 100000000):
if i == 10000:
break
t2 = timeit.default_timer()
print "time taken: ", (t2-t1) # 2.78506207466 seconds
を使用するとrange
、0〜100000000(時間がかかる)のリストが既に作成されていますxrange
が、ジェネレーターであり、必要に基づいて、つまり反復が継続する場合にのみ数値を生成します。
Python-3では、range
機能の実装はxrange
Python-2 と同じですがxrange
、Python-3では廃止されています。
ハッピーコーディング!!
range(x,y)
for
ループを使用する場合、xとyの間の各数値のリストを返しますが、range
速度は遅くなります。実際、range
インデックスの範囲が大きくなっています。range(x.y)
xとyの間のすべての数値のリストを出力します
xrange(x,y)
戻りますxrange(x,y)
が、for
ループを使用した場合xrange
は高速です。xrange
インデックスの範囲が狭くなっています。xrange
印刷するxrange(x,y)
だけでなく、そこにあるすべての数値を保持します。
[In] range(1,10)
[Out] [1, 2, 3, 4, 5, 6, 7, 8, 9]
[In] xrange(1,10)
[Out] xrange(1,10)
for
ループを使用すると、うまくいくでしょう
[In] for i in range(1,10):
print i
[Out] 1
2
3
4
5
6
7
8
9
[In] for i in xrange(1,10):
print i
[Out] 1
2
3
4
5
6
7
8
9
ループを使用してもそれほど大きな違いはありませんが、印刷するだけでは違いがあります。
range(): range(1、10)は、1〜10個の数値のリストを返し、リスト全体をメモリに保持します。
xrange(): range()と同様ですが、リストを返す代わりに、要求に応じて範囲内の数値を生成するオブジェクトを返します。ループの場合、これはrange()よりもわずかに高速で、メモリ効率が向上します。イテレータのようなxrange()オブジェクトで、オンデマンドで数値を生成します(遅延評価)
In [1]: range(1,10)
Out[1]: [1, 2, 3, 4, 5, 6, 7, 8, 9]
In [2]: xrange(10)
Out[2]: xrange(10)
In [3]: print xrange.__doc__
xrange([start,] stop[, step]) -> xrange object
他の回答の一部は、Python 3は2.xの者を排除することを言及するrange
と2.xのと改名xrange
しますrange
。ただし、3.0または3.1(だれもがそうであるべきではない)を使用している場合を除き、実際には多少異なる型です。
3.1ドキュメントは言います:
範囲オブジェクトの動作はほとんどありません
len
。インデックスオブジェクト、反復、および関数のみをサポートします。
ただし、3.2以降でrange
は、は完全なシーケンスです。これは、拡張スライスと、とcollections.abc.Sequence
同じセマンティクスを持つすべてのメソッドをサポートしlist
ます。*
そして、少なくともCPythonとPyPy(現在存在する2つ以上の3.2+実装)では、index
and count
メソッドとin
演算子の定数時間実装も(整数のみを渡す限り)あります。これは、執筆123456 in r
が3.2+以降では妥当であることを意味しますが、2.7または3.1では恐ろしい考えになります。
* 2.6-2.7および3.0-3.1 でissubclass(xrange, collections.Sequence)
戻るという事実True
は、 3.2で修正されたバグであり、バックポートされていません。
Python 2.xの場合
range(x)は、メモリ内にx要素で作成されるリストを返します。
>>> a = range(5)
>>> a
[0, 1, 2, 3, 4]
xrange(x)は、オンデマンドで数値を生成するジェネレータobjであるxrangeオブジェクトを返します。これらはforループ(遅延評価)中に計算されます。
ループの場合、これはrange()よりわずかに高速で、メモリ効率が向上します。
>>> b = xrange(5)
>>> b
xrange(5)
xrange()
ジェネレータではありません。xrange(n)
.__ iter __() `です。
ループでxrangeに対して範囲をテストするとき(私はtimeitを使用する必要があることを知っていますが、これは単純なリスト内包例を使用してメモリからすばやくハッキングされました)、次のことがわかりました。
import time
for x in range(1, 10):
t = time.time()
[v*10 for v in range(1, 10000)]
print "range: %.4f" % ((time.time()-t)*100)
t = time.time()
[v*10 for v in xrange(1, 10000)]
print "xrange: %.4f" % ((time.time()-t)*100)
それは与える:
$python range_tests.py
range: 0.4273
xrange: 0.3733
range: 0.3881
xrange: 0.3507
range: 0.3712
xrange: 0.3565
range: 0.4031
xrange: 0.3558
range: 0.3714
xrange: 0.3520
range: 0.3834
xrange: 0.3546
range: 0.3717
xrange: 0.3511
range: 0.3745
xrange: 0.3523
range: 0.3858
xrange: 0.3997 <- garbage collection?
または、forループでxrangeを使用します。
range: 0.4172
xrange: 0.3701
range: 0.3840
xrange: 0.3547
range: 0.3830
xrange: 0.3862 <- garbage collection?
range: 0.4019
xrange: 0.3532
range: 0.3738
xrange: 0.3726
range: 0.3762
xrange: 0.3533
range: 0.3710
xrange: 0.3509
range: 0.3738
xrange: 0.3512
range: 0.3703
xrange: 0.3509
スニペットは適切にテストされていますか?xrangeの遅いインスタンスに関するコメントはありますか?またはより良い例:-)
xrange
少し高速に見えましたが、Python 3では比較が冗長になりました。
timeit
目的です。これは、最高の時計代わりに使用して、GCを無効にすることを、何度も実行しているの世話をするtime
など、
pythonのxrange()とrange()はユーザーの場合と同様に機能しますが、両方の関数を使用してメモリがどのように割り当てられるかを話しているときに違いが生じます。
range()を使用する場合は、生成するすべての変数にメモリを割り当てます。そのため、より大きなnoでの使用は推奨されません。生成される変数の。
一方、xrange()は一度に特定の値のみを生成し、必要なすべての値を出力するためにforループでのみ使用できます。
何?
range
実行時に静的リストを返します。
xrange
を返しますobject
必要なときのように、そこからの値が生成される(それは確かではないですが、発電機のように機能します)。
いつ使用するのですか?
xrange
特に携帯電話のような「メモリに敏感なシステム」を持っているときに、10億と言った巨大な範囲のリストを生成したい場合にます。range
リストを数回繰り返したい場合に使用します。PS:Python 3.xのrange
関数== Python 2.xのxrange
関数。
xrange
ジェネレータオブジェクトを返しません。
誰もがそれを大きく説明しました。しかし、私はそれを自分の目で見てほしかった。私はpython3を使用しています。そこで、Windowsでリソースモニターを開き、最初に次のコマンドを最初に実行しました。
a=0
for i in range(1,100000):
a=a+i
次に、「使用中」のメモリの変更を確認しました。ささいなことでした。次に、次のコードを実行しました。
for i in list(range(1,100000)):
a=a+i
そして、それはすぐに使用するためにメモリの大きなチャンクを必要としました。そして、私は確信しました。自分で試すことができます。
Python 2Xを使用している場合は、最初のコードで「range()」を「xrange()」に、「list(range())」を「range()」に置き換えます。
ヘルプドキュメントから。
Python 2.7.12
>>> print range.__doc__
range(stop) -> list of integers
range(start, stop[, step]) -> list of integers
Return a list containing an arithmetic progression of integers.
range(i, j) returns [i, i+1, i+2, ..., j-1]; start (!) defaults to 0.
When step is given, it specifies the increment (or decrement).
For example, range(4) returns [0, 1, 2, 3]. The end point is omitted!
These are exactly the valid indices for a list of 4 elements.
>>> print xrange.__doc__
xrange(stop) -> xrange object
xrange(start, stop[, step]) -> xrange object
Like range(), but instead of returning a list, returns an object that
generates the numbers in the range on demand. For looping, this is
slightly faster than range() and more memory efficient.
Python 3.5.2
>>> print(range.__doc__)
range(stop) -> range object
range(start, stop[, step]) -> range object
Return an object that produces a sequence of integers from start (inclusive)
to stop (exclusive) by step. range(i, j) produces i, i+1, i+2, ..., j-1.
start defaults to 0, and stop is omitted! range(4) produces 0, 1, 2, 3.
These are exactly the valid indices for a list of 4 elements.
When step is given, it specifies the increment (or decrement).
>>> print(xrange.__doc__)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'xrange' is not defined
違いは明らかです。Python 2.xでは、range
リストをxrange
返し、反復可能なxrangeオブジェクトを返します。
Pythonの3.xのでは、range
となっxrange
たPython 2.xのの、およびxrange
削除されます。
0-Nアイテムのスキャン/印刷の要件では、範囲とxrangeは次のように機能します。
range()-メモリ内に新しいリストを作成し、0からNアイテム全体(合計N + 1)を取得して出力します。xrange()-アイテムをスキャンして現在検出されたアイテムのみをメモリに保持するイテレータインスタンスを作成し、常に同じ量のメモリを使用します。
必要な要素がリストの先頭にある場合にのみ、時間とメモリを大幅に節約できます。
xrange
イテレータインスタンスを作成しません。これは、xrange
反復可能ではあるがイテレータではないオブジェクトを作成します。リストのように、ほとんど(ただし完全ではない)シーケンスです。
範囲は、戻りリストをしながらはxrangeを返すはxrangeの範囲を使用する場合には、すべての要素を一度に生成されるのに対し、この場合には、一つだけの要素が生成され、反復ごとに使用可能なように、範囲の大きさにかかわらず、同じメモリを取るオブジェクトおよびメモリで利用可能です。
range(..)
/ への引数が小さいほど、差は小さくなりますxrange(..)
。
$ python -m timeit "for i in xrange(10111):" " for k in range(100):" " pass"
10 loops, best of 3: 59.4 msec per loop
$ python -m timeit "for i in xrange(10111):" " for k in xrange(100):" " pass"
10 loops, best of 3: 46.9 msec per loop
この場合xrange(100)
、効率は約20%だけです。
さらに、do list(xrange(...))
は次と同等になりますrange(...)
ます。
そう list
遅いです。
また xrange
、シーケンスを完全に完了していません
それがリストではなくxrange
オブジェクトだからです
range()
Pythonで 2.x
この関数は、本質的にはrange()
Python 2.x
で使用可能であった古い関数でありlist
、指定された範囲の要素を含むオブジェクトのインスタンスを返します。
ただし、この実装は、ある範囲の数値でリストを初期化する場合、非効率的です。たとえばfor i in range(1000000)
、このリストをメモリに格納する必要があるため、メモリと時間の両方の観点から実行するには非常にコストのかかるコマンドになります。
range()
Python 3.x
およびxrange()
Python2.x
Python 3.x
は、の新しい実装を導入しましたrange()
(新しい実装は2.x
、xrange()
関数を)。
range()
知られている戦略活用遅延評価を。範囲内の要素の膨大なリストを作成する代わりに、新しい実装range
では、指定された範囲内の必要な要素を表す軽量なオブジェクトであるclassを導入します。これらは明示的にメモリに格納しません(これはジェネレーターのように聞こえるかもしれませんが、遅延評価の概念は異なる)。
例として、以下を検討してください。
# Python 2.x
>>> a = range(10)
>>> type(a)
<type 'list'>
>>> b = xrange(10)
>>> type(b)
<type 'xrange'>
そして
# Python 3.x
>>> a = range(10)
>>> type(a)
<class 'range'>