2013-10-21 35 views
5

當在Python 3計算所有以前的值,範圍支持索引,但我不知道那究竟是如何工作的。確實具有範圍使用索引

例如:range(100000000000000000000000000)[-1]

我有一個基本的理解是,範圍函數實際上返回一對象,該對象佔用的內存量有限。這是否意味着要達到最後的價值,它必須計算所有以前的價值?

+3

這不是真正切片符號。切片使用冒號如':'。這只是索引/下標的一種特殊形式。 – Shashank

+0

哦,你是對的!這樣愚蠢的錯誤。 – PaulC

回答

8

不要求獲得前值獲得的最後一個值。

它由compute_item function(它被compute_range_item < - range_item ...調用)計算。

通過Python 3.3的源代碼(對象/ rangeobjects.c)

static PyObject * 
compute_item(rangeobject *r, PyObject *i) 
{ 
    PyObject *incr, *result; 
    /* PyLong equivalent to: 
    * return r->start + (i * r->step) 
    */ 
    incr = PyNumber_Multiply(i, r->step); 
    if (!incr) 
     return NULL; 
    result = PyNumber_Add(r->start, incr); 
    Py_DECREF(incr); 
    return result; 
} 
+5

嗯..知道爲什麼'timeit.timeit( '範圍(9999999999999)[ - 1]')'花費的時間比'timeit.timeit長近30%( '範圍(9999999999999)[1]')'? – aIKid

+1

@aIKid,負指數應轉換爲正指數。我沒有分析它(我現在不能)。這可能是一個原因。 [**從源代碼**中查看此行](http://hg.python.org/cpython/file/d8e352e2f110/Objects/rangeobject.c#l260)。 – falsetru

+2

@aIKid,還有另外一個可能的原因。 '範圍(9999999999999)[ - 1]'返回'9999999999998',而範圍(9999999999999)[1]'返回'1'。 '1'需要28個字節(並在CPython中實現),'9999999999998'需要32個字節。 (CPython 3.3.2 64bit)。多次分配/取消分配對象可能需要一些時間。 – falsetru

2

也許不是:

import timeit 
print(timeit.timeit('range(10)[-1]')) 
>>> 0.5438045680057257 

print(timeit.timeit('range(100000000000000000000000000)[-1]')) 
>>> 0.7502937959798146