2013-10-21 7 views
5

In python 3, l'intervallo supporta l'indicizzazione, ma mi chiedo esattamente come funzioni.L'intervallo deve calcolare tutti i valori precedenti quando si utilizza un indice

Ad esempio: range(100000000000000000000000000)[-1]

Ho una conoscenza di base che la funzione range restituisce effettivamente un oggetto intervallo che prende una quantità limitata di memoria. Significa che per ottenere l'ultimo valore, deve calcolare tutti i valori precedenti?

+3

che non è proprio affettare la notazione. La slicing usa due punti come ':'. Questa è solo una forma speciale di indicizzazione/sottoscrizione. – Shashank

+0

Oh, hai ragione! Un errore così sciocco. – PaulC

risposta

8

Non è necessario per ottenere il valore precedente per ottenere l'ultimo valore.

Viene calcolato da compute_item function (che viene chiamato da compute_range_item < - range_item ...).

da Python 3.3 il codice sorgente (Oggetti/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

Hm .. Qualche idea sul perché 'timeit.timeit ('range (9999999999999) [- 1]')' richiede circa il 30% in più rispetto a 'timeit.timeit ('range (9999999999999) [1]')'? – aIKid

+1

@aikid, l'indice negativo deve essere convertito in indice positivo. Non l'ho profilato (non posso ora). Questa potrebbe essere una delle ragioni. [** Guarda questa riga dal codice sorgente **] (http://hg.python.org/cpython/file/d8e352e2f110/Objects/rangeobject.c#l260). – falsetru

+2

@aikid, C'è un altro possibile motivo. 'range (999999999999999) [- 1]' restituisce '9999999999998', mentre' range (9999999999999) [1] 'restituisce' 1'. '1' richiede 28 byte (e internato in CPython),' 9999999999998' richiede 32 byte. (CPython 3.3.2 64 bit). L'allocazione/deallocazione di oggetti più volte può richiedere un po 'di tempo. – falsetru

2
Probabilmente no

:

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

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