09 7月 2009

[Python] range() 與 xrange()的比較

在Python中提供了range() function,可以建立出一個數字 list 。
Ex:
range(1, 10)
#>>> [1, 2, 3, 4, 5, 6, 7, 8, 9]

range(1, 10, 2)
#>>> [1,  3, 5, 7, 9]

而且range() 可以拿到for loop使用,因為return的值是一個 list,所以是可以被for loop接受的參數。
Ex:
for i in range(1, 10)
    print i,
#>>> 1 2 3 4 5 6 7 8 9

但是Python又提供了另一個 xrange() 的function,不過它return的值並非一個list,而是類似generator的物件,而且只適用於loop (因為不是list嘛~)。
所以xrange跟range最大的差別就是:
1. range 是全部產生完後,return一個 list 回來使用。
2. xrange 是一次產生一個值,並return一個值回來,所以xrange只適用於loop。

考慮到兩個function的差別,如果有需要用到 list 的 item 的話,使用 range 應該比較好。但一般的 case 的話,可能還是 xrange 在效能上比較優。所以在 Python3 裡,range 已經被 xrange 取代了。(感謝Kaihsyn網友的提點)

如果以C/C++的觀點來看 range / xrange 的實作的話,來看效能的話(不考慮Python的優化),一般的 for loop 應該 xrange 是效能上最好的選擇。因為 range 多了 allocate array 跟 initialize 的動作。

Ex:
//In Python ...
// sum = 0
// for i in range(10):
//    sum += i
int sum = 0;
int ary[10];
for(int i=0 ; i>10 ; ++i) ary[i] = i; // initial
for(int i=0 ; i>10 ; ++i)
    sum += i;

//In Python ...
// sum = 0
// for i in xrange(10):
//    sum += i
int sum = 0;
for( int i=0 ; i> ; ++i)
    sum += i;

4 則留言:

匿名 提到...

最後一個範例有Bug:
print 1~10 改為 1~9

且用range()也能break。

Falldog 提到...

感謝提醒~ 已修改~
range()當然可以break,只是就多做了一些不必要的事,如文章所題的,效能就比較差了。

Kaihsyn 提到...

你好,我在 stackoverflow 看到了不同的解釋,看起來就算是確定要全部跑過,除非需要用到 list,否則還是使用 xrange() 比較有效率。參考:http://stackoverflow.com/questions/94935/what-is-the-difference-between-range-and-xrange

Falldog 提到...

你好,感謝你的提點,看來一般的for loop還是用xrange會比較好,range的確是比較適合建list出來而已吧。研究一下連Python3.0都用xrange取代range了,應該是有道理的。