A range()
l'oggetto calcola i numeri su richiesta, ad es. quando ripetuti su o quando si tenta di accedere a indici specifici:
>>> r = range(2, 80, 3)
>>> len(r)
26
>>> r[15]
47
>>> 42 in r
False
>>> r[:10]
range(2, 32, 3)
Si tratta di una sequenza in quanto l'oggetto supporta il controllo di appartenenza, l'indicizzazione, affettare e ha una lunghezza, proprio come una lista o una tupla. Ma, a differenza di una lista o di una tupla, in realtà non contiene tutti gli interi nella sequenza in memoria, rendendolo virtuale.
Quando si chiama list()
su un oggetto range()
, si sta creando una nuova sequenza che contiene tutti i numeri interi che si trovano nella gamma, ma ora si sta memorizzando tutti quei numeri interi:
>>> r_list = list(r)
>>> r_list
[2, 5, 8, 11, 14, 17, 20, 23, 26, 29, 32, 35, 38, 41, 44, 47, 50, 53, 56, 59, 62, 65, 68, 71, 74, 77]
Questa è una sequenza di troppo, ma ci vuole più memoria dato che tutti gli interi ora vengono prodotti in anticipo, se li userete o meno. Quindi una lista o una tupla è una sequenza di concreta.
Utilizzando la sys.getsizeof()
function, possiamo calcolare la quantità di memoria ogni oggetto usa:
>>> import sys
>>> sys.getsizeof(r)
48
>>> sys.getsizeof(r_list) + sum(sys.getsizeof(i) for i in r_list)
1072
L'oggetto elenco utilizza 22 volte la memoria; questo perché contiene 26 oggetti interi.
E per rispondere al commento sulla tua domanda, gli oggetti range()
sono noniterators. Gli iteratori producono valori uno alla volta su richiesta, ma non possono essere indicizzati, producono tutti i valori solo una volta e non possono essere indicizzati. È possibile produrre un iteratore da un oggetto range()
con la iter()
function:
>>> iter(r)
<range_iterator object at 0x10aea23f0>
>>> r_iter = iter(r)
>>> len(r_iter)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: object of type 'range_iterator' has no len()
>>> list(r_iter)
[2, 5, 8, 11, 14, 17, 20, 23, 26, 29, 32, 35, 38, 41, 44, 47, 50, 53, 56, 59, 62, 65, 68, 71, 74, 77]
>>> list(r_iter)
[]
ma una volta esaurita, l'iteratore non produrrà più la stessa gamma.
Tutto quanto sopra si applica principalmente a Python 3; in Python 2 il tipo è chiamato xrange()
, dove è più limitato nelle sue capacità (non supporta l'affettatura e può gestire solo interi < sys.maxint
).
'range()' in python 3 restituisce un iteratore. 'range()' in python 2 restituisce una 'lista'. – tyteen4a03
@ tyteen4a03 - Non esattamente. 'range' restituisce una sequenza pigra di tipo' range'. I suoi articoli sono calcolati su richiesta. Ma puoi riutilizzare gli oggetti 'range' mentre gli iteratori sono una tantum (una volta iterato su di essi, sono esauriti). – iCodez
@iCodez TIL. :) – tyteen4a03