いくつかのパフォーマンス測定。を使用timeit
して手動で実行する代わりに使用しtime
ます。
まず、Apple 2.7.2 64ビット:
In [37]: %timeit collections.deque((x for x in xrange(10000000) if x%4 == 0), maxlen=0)
1 loops, best of 3: 1.05 s per loop
今、python.org 3.3.0 64ビット:
In [83]: %timeit collections.deque((x for x in range(10000000) if x%4 == 0), maxlen=0)
1 loops, best of 3: 1.32 s per loop
In [84]: %timeit collections.deque((x for x in xrange(10000000) if x%4 == 0), maxlen=0)
1 loops, best of 3: 1.31 s per loop
In [85]: %timeit collections.deque((x for x in iter(range(10000000)) if x%4 == 0), maxlen=0)
1 loops, best of 3: 1.33 s per loop
どうやら、3.xはrange
実際には2.xより少し遅いですxrange
。そしてOPのxrange
機能はそれとは何の関係もありません。(__iter__
スロットへの1回限りの呼び出しは、ループ内で発生したすべての呼び出しに対する10000000の呼び出しの中で表示される可能性は低いので、当然のことですが、誰かがそれを可能性として持ち出しました。)
しかし、それはわずか30%遅くなります。OPはどのように2倍遅くなったのですか?まあ、32ビットPythonで同じテストを繰り返すと、1.58対3.12になります。したがって、これは、3.xが32ビットに害を及ぼすような方法で64ビットパフォーマンス用に最適化された場合のもう1つのケースだと思います。
しかし、それは本当に重要ですか?3.3.0 64ビットでもう一度確認してください:
In [86]: %timeit [x for x in range(10000000) if x%4 == 0]
1 loops, best of 3: 3.65 s per loop
したがって、の作成にlist
は、全体の反復よりも2倍以上長い時間がかかります。
そして、「Python 2.6+よりもはるかに多くのリソースを消費する」については、私のテストから、3.x range
は2.x xrange
とまったく同じサイズであるように見えます。さらに、10倍のサイズであっても、不要なリストを作成します。それでも、範囲の反復で何ができるかよりも約10000000x多い問題です。
そして、for
内部のCループの代わりに明示的なループはdeque
どうですか?
In [87]: def consume(x):
....: for i in x:
....: pass
In [88]: %timeit consume(x for x in range(10000000) if x%4 == 0)
1 loops, best of 3: 1.85 s per loop
そのため、for
ステートメントを反復する実際の作業と同じくらいの時間をステートメントで無駄にしましたrange
。
範囲オブジェクトの反復の最適化について心配している場合は、おそらく間違った場所を探しているでしょう。
その間、xrange
同じことを何回言われたとしても、なぜ削除されたのかと尋ね続けますが、繰り返します。削除されませんでした。名前がに変更されrange
、2.x range
が削除されました。
3.3 range
オブジェクトが2.x xrange
オブジェクトの直接の子孫であり(2.x range
関数の子孫ではない)ことを証明するいくつかの例を次に示します:3.3range
および2.7のxrange
ソース。変更履歴も確認できます(ファイルの任意の場所にある文字列 "xrange"の最後のインスタンスを置き換えた変更にリンクされていると思います)。
では、なぜ遅いのでしょうか?
まあ、一つには、彼らは多くの新機能を追加しました。もう1つの理由として、彼らはあらゆる場所(特に反復の内部)であらゆる種類の変更を行っており、小さな副作用があります。そして、重要度の低いケースをわずかに悲観的にすることさえあるとしても、さまざまな重要なケースを劇的に最適化する多くの作業がありました。これをすべて足し合わせれば、range
できるだけ速く反復することが少し遅くなったとしても驚くことではありません。これはそれほど重要ではないケースの1つであり、誰も集中するほど十分に気にすることはありません。このパフォーマンスの違いがコード内のホットスポットである実際のユースケースを誰も持つ可能性はほとんどありません。
range
Python 3.xではxrange
、Python 2.xからのものです。range
削除されたのは、実際にはPython 2.x でした。