1. 程式人生 > >python中xrange和range

python中xrange和range

說到序列,我們第一想到的是一組有序元素組成的集合。同時,每個元素都有唯一的下標作為索引。
在Python中,有許多內界的序列。包括元組tuple,列表list,字串str等。上面提到的序列型別(list,tuple,str)有一個共同的特點,就是當序列物件建立時,需要開闢專門的記憶體空間,儲存序列中的所有元素。換句話說,這些序列物件本質上,是一個集合。
例如,下面程式碼建立了一個序列物件s。在該物件序列建立時,需要開闢記憶體空間將序列中的3個元素(整數1,2,3)儲存下來。

s=[1,2,3]  

然而,根據python官方文件的定義,一個序列物件不必要儲存所有的元素。一般來說,一個序列物件至少需要實現如下兩個方法。
- _len_

方法。該方法返回序列長度,也即序列中元素個數。
- _getitem_方法。該方法有一個整型引數(不妨記為index)。它需要返回序列中下標為index的元素的值。
例如,下面的程式碼定義了一個序列型別。

class MyRange:  
    def __init__(self, start, end):  
        self.start = start  
        self.end = end  

    def __len__(self):  
        return self.end - self.start  

    def __getitem__
(self, index):
if index < 0 or index >= len(self): raise IndexError return index + self.start

它定義的是從start到end-1之間所有整陣列成的序列。

  • 程式碼中的len方法返回序列的長度。
  • 程式碼中的_getitem_方法返回序列中第index個元素。其中第10-11行判斷index的是否越界。值得一提的是,第10行呼叫的len方法是Python的內建方法,它會呼叫序列物件的_len_方法。可以想見,_getitem_
    方法其實實現了序列物件的通項公式。
    下面的測試程式碼
myrange = MyRange(0, 10)  
print myrange[9]  
print myrange[10] 

輸出如下

Traceback (most recent call last):  
  File "test.py", line 25, in <module>  
    print myrange[10]  
  File "test.py", line 19, in __getitem__  
    raise IndexError  
IndexError

當然,在Python中,序列的下標是可以為負的。因此,我們對getitem方法做如下修改。

class MyRange:  
    def __getitem__(self, index):  
        index = index if index >= 0 else index + self.end  
        if index < 0 or index >= len(self):  
            raise IndexError  
        return index + self.start 

測試程式碼

myrange = MyRange(0, 10)  
print myrange[-1]  
print myrange[-2] 

輸出結果

9  
8

有了上面的介紹以後,我們可以很容易理解python中range方法與xrange方法區別了。

range方法返回的是一個list物件,它需要開闢專門的空間儲存序列中所有的元素。
xrange方法返回的是xrange物件,它是一個序列物件,但並不儲存序列中的元素。其實現方法與本文介紹的MyRange型別類似。

因此,如果只對序列進行讀操作,xrange方法效率較高;但是如果需要改變序列的元素,或者需要往序列增刪元素,那隻能通過range方法生成一個list物件。