web-dev-qa-db-ja.com

Python 2.Xのrange関数とxrange関数の違いは何ですか?

どうやらxrangeは速いのですが、なぜそれが速いのか(そしてこれまでのところ逸話のほかに証明がないのか)、あるいはそれ以外に何が違うのかわかりません。

for i in range(0, 20):
for i in xrange(0, 20):
660
Teifion

rangeはリストを作成するので、range(1, 10000000)を実行すると、メモリ内に9999999要素を持つリストが作成されます。

xrangeは遅延評価されるシーケンスオブジェクトです。

Python3ではrangeはpythonのxrangeと同等の働きをするという、@ Thiagoのヒントから付け加えるべきです。

749
Charles

rangeはリストを作成するので、range(1, 10000000)を実行すると、9999999要素を使ってメモリ内にリストを作成します。

xrange ジェネレータなので シーケンスオブジェクト です それは怠惰に評価されます。

これは事実ですが、Python 3では.range()はPython 2 .xrange()によって実装されます。あなたが実際にリストを生成する必要があるならば、あなたはする必要があるでしょう:

list(range(1,100))
217
Corey

覚えておいて、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()はイテレータの振る舞いを良くします。

107
John Fouhy

xrangeはrangeパラメータだけを格納し、必要に応じて数値を生成します。しかし、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のように振る舞いますが、最小と最大のエンドポイントへの制限はありません。

64
efotinis

xrangeはイテレータを返し、一度に1つの数だけメモリに保持します。 rangeは数字のリスト全体をメモリに保存します。

38
Ben Hoffstein

Library Reference に時間をかけてください。あなたがそれに慣れているほど、このような質問に対する答えを早く見つけることができます。特に重要なのは、組み込みのオブジェクトと型に関する最初の数章です。

Xrange型の利点は、xrangeオブジェクトが表す範囲のサイズに関係なく、xrangeオブジェクトは常に同じ量のメモリを使用することです。一貫したパフォーマンス上の利点はありません。

Pythonの構成体に関する簡単な情報を見つけるもう一つの方法はdocstringとhelp-functionです:

print xrange.__doc__ # def doc(x): print x.__doc__ is super useful
help(xrange)
28
Antti Rasinen

私は誰も読んでショックを受けていません doc

この関数はrange()に非常に似ていますが、リストの代わりにxrangeオブジェクトを返します。これは不透明なシーケンス型で、対応するリストと同じ値になりますが、実際にはそれらをすべて同時に格納することはしません。メモリ不足のマシンで非常に広い範囲が使用されている場合、または使用されている場合を除き、xrange()に対するrange()の利点は最小限です(xrange()は要求時に値を作成する必要があるため)。範囲のすべての要素が使用されることはありません(通常、ループがbreakで終了する場合など)。

13
Kishor Pawar

rangeはリストを作成します。したがって、range(1、10000000)を実行すると、メモリ内に10000000要素のリストが作成されます。 xrangeはジェネレータなので、遅延評価されます。

これには2つの利点があります。

  1. MemoryErrorを取得せずに長いリストを繰り返すことができます。
  2. 各数値を遅延的に解決するので、反復を早く停止しても、リスト全体を作成する時間を無駄にすることはありません。
12
Lucas S.

最適化のためです。

range()は開始から終了までの値のリストを作成します(あなたの例では0 .. 20)。これは非常に広い範囲では高価な操作になります。

一方、xrange()ははるかに最適化されています。 (xrangeシーケンスオブジェクトを介して)必要なときに次の値を計算するだけで、range()のようにすべての値のリストを作成することはしません。

10
QAZ

この簡単な例では、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の場合には、実質的により良いものを反映していません。

rangexrangeと比べて本当に遅い、次のケースを見てください。

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機能の実装はPython-2のxrangeの実装と同じですが、Python-3ではxrangeを廃止しました。

ハッピーコーディング!

10
User_Targaryen

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
8
Tushar.PUCSD

forループを使用する場合、range(x,y)はxとyの間にある各数値のリストを返します。その後、rangeは遅くなります。実際、rangeはより大きなインデックス範囲を持っています。 range(x.y)はxとyの間にあるすべての数のリストを表示します

xrange(x,y)xrange(x,y)を返しますが、forループを使用した場合はxrangeの方が速くなります。 xrangeは、小さいインデックス範囲を持ちます。 xrangexrange(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

ループを使用しても大きな違いはありませんが、印刷するだけで違いはあります。

8
Supercolbat

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)
6
SrmHitter9062

ループ内でxrangeに対してrangeをテストするとき(私は 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の遅いインスタンスについてのコメントはありますか?あるいはもっと良い例:-)

5
Dave Everitt

他の回答の中には、Python 3が2.xのrangeを廃止し、2.xのxrangerangeに改名したと述べている人もいます。ただし、3.0または3.1を使用しているのでない限り(どちらを使用してもいけない)、実際には多少異なるタイプです。

として3.1ドキュメント 言う:

範囲オブジェクトは、ほとんど動作がありません。それらは、インデックス付け、繰り返し、およびlen関数のみをサポートします。

しかし、3.2以降では、rangeは完全なシーケンスです。これは拡張スライス、およびlistと同じ意味を持つ collections.abc.Sequence のすべてのメソッドをサポートします。*

そして、少なくともCPythonとPyPy(現在存在する唯一の2つの3.2+実装)では、indexcountメソッドと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で修正されバックポートされませんでした。

5
abarnert

pythonのxrange()とrange()はユーザーと同じように動作しますが、違いは両方の関数を使ってメモリがどのように割り当てられるかについて話しているときに生じます。

Range()を使っているときは、それが生成しているすべての変数にメモリを割り当てるので、より大きいnoを付けて使うことはお勧めできません。生成される変数の数。

一方、xrange()は一度に特定の値のみを生成し、forループでのみ使用して必要なすべての値を出力できます。

4

グラフィカル分析によるrangeとxrangeの比較については、次の記事を読んでください。

Pythonの範囲対xrange

3
Harsha Vardhan

rangeはリスト全体を生成してそれを返します。 xrangeはしません - 要求に応じてリストに数字を生成します。

3
Eddie Deyo

何?
rangeは実行時に静的リストを返します。
xrangeは、必要に応じて必要に応じて値が生成されるobject(これは確かに1つではありませんが、ジェネレータのように機能します)を返します。

いつ使うの?

  • 特に携帯電話のような「メモリに敏感なシステム」があるときに、10億など、巨大な範囲のリストを生成したい場合は、xrangeを使用してください。
  • リストを数回反復したい場合はrangeを使用してください。

シモンズ:Python 3.xのrange関数== Python 2.xのxrange関数。

2
kmario23

xrangeはイテレータを使用し(その場で値を生成します)、rangeはリストを返します。

2
hacama

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%です。

1
Evgeni Sergeev

0〜N項目のスキャン/印刷の要件では、rangeとxrangeは次のように機能します。

range() - メモリに新しいリストを作成し、0からNまでの項目全体(合計N + 1)を取り出してそれらを印刷します。 xrange() - アイテムをスキャンして現在遭遇しているアイテムだけをメモリに保存するイテレータインスタンスを作成します。したがって、常に同じ量のメモリを使用します。

必要な要素がリストの先頭にある場合は、かなりの時間とメモリを節約できます。

1
SomeDoubts

誰もがそれを大いに説明しました。しかし、私は自分自身でそれを見ることを望みました。私は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()'にそれぞれ置き換えてください。

1
ANKUR SATYA

ヘルプドキュメントから。

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はPython 2.xのxrangeになり、xrangeは削除されました。

0
Rajendra Uppal

Range list を返します/ while xrange は範囲サイズに関係なく同じメモリを使用する xrange オブジェクトを返します。一方、rangeを使用する場合は、すべての要素が一度に生成され、メモリ内で利用可能になります。

0
user299567

range:-rangeは、一度にすべてを設定します。つまり、範囲内のすべての番号がメモリを占有します。

xrange:-xrangeはgeneratorのようなものです。数値の範囲が欲しいときには思い浮かぶでしょうが、for loop.soでメモリ効率を上げたいときのように、それらを格納したくないのです。

0
tejaswini teju

さらに、do list(xrange(...))range(...)と同等になります。

だからlistは遅いです。

またxrangeは実際には完全にシーケンスを終了しません

だから、リストではなく、xrangeオブジェクトなのです。

0
U9-Forward