Risposte:
In Python 2.x:
range
crea un elenco, quindi se lo fai range(1, 10000000)
crea un elenco in memoria con 9999999
elementi.
xrange
è un oggetto sequenza che valuta pigramente.
In Python 3, range
fa l'equivalente di Python xrange
e, per ottenere l'elenco, devi usare list(range(...))
.
xrange(x).__iter__()
è un generatore.
i
viene valutato su richiesta anziché su inizializzazione.
range crea un elenco, quindi se lo fai
range(1, 10000000)
crea un elenco in memoria con9999999
elementi.
xrange
è un generatore, quindiè un oggetto sequenzaè unache valuta pigramente.
Questo è vero, ma in Python 3 .range()
sarà implementato da Python 2 .xrange()
. Se è necessario generare effettivamente l'elenco, è necessario:
list(range(1,100))
xrange
un generatore? È una funzione che contiene yield
un'istruzione e secondo il glossario tali funzioni sono chiamate generatori.
Ricorda, usa il timeit
modulo per testare quale dei piccoli frammenti di codice è più veloce!
$ python -m timeit 'for i in range(1000000):' ' pass'
10 loops, best of 3: 90.5 msec per loop
$ python -m timeit 'for i in xrange(1000000):' ' pass'
10 loops, best of 3: 51.1 msec per loop
Personalmente, uso sempre .range()
, a meno che non abbia a che fare con elenchi davvero enormi - come puoi vedere, in termini di tempo, per un elenco di un milione di voci, l'overhead aggiuntivo è di soli 0,04 secondi. E come sottolinea Corey, in Python 3.0 .xrange()
sparirà e .range()
ti darà comunque un buon comportamento da iteratore.
python -m timeit "for i in xrange(1000000):" " pass"
the extra overhead is only 0.04 seconds
non è il modo corretto di esaminarla, (90.5-51.1)/51.1 = 1.771 times slower
è corretta perché trasmette che se questo è il ciclo principale del tuo programma, può potenzialmente colmare il collo di bottiglia. Tuttavia, se questa è una piccola parte, 1.77x non è molto.
xrange
memorizza solo i parametri di intervallo e genera i numeri su richiesta. Tuttavia l'implementazione C di Python attualmente limita i suoi argomenti a C long:
xrange(2**32-1, 2**32+1) # When long is 32 bits, OverflowError: Python int too large to convert to C long
range(2**32-1, 2**32+1) # OK --> [4294967295L, 4294967296L]
Si noti che in Python 3.0 c'è solo range
e si comporta come il 2.x xrange
ma senza le limitazioni sui punti minimo e massimo.
xrange restituisce un iteratore e mantiene un solo numero in memoria alla volta. range mantiene l'intero elenco di numeri in memoria.
xrange
non non restituisce un iteratore.
and only keeps one number in memory at a time
e dove sono collocati gli altri, per favore
Trascorri del tempo con il riferimento alla libreria . Più familiarità con esso, più veloce è possibile trovare risposte a domande come questa. Particolarmente importanti sono i primi capitoli su oggetti e tipi incorporati.
Il vantaggio del tipo xrange è che un oggetto xrange occuperà sempre la stessa quantità di memoria, indipendentemente dalla dimensione dell'intervallo che rappresenta. Non ci sono vantaggi prestazionali costanti.
Un altro modo per trovare rapidamente informazioni su un costrutto Python è il docstring e la funzione di aiuto:
print xrange.__doc__ # def doc(x): print x.__doc__ is super useful
help(xrange)
Sono scioccato che nessuno legga doc :
Questa funzione è molto simile a
range()
, ma restituisce unxrange
oggetto anziché un elenco. Questo è un tipo di sequenza opaca che produce gli stessi valori dell'elenco corrispondente, senza effettivamente memorizzarli tutti contemporaneamente. Il vantaggio dixrange()
overrange()
è minimo (poichéxrange()
deve ancora creare i valori quando richiesto) tranne quando viene utilizzato un intervallo molto ampio su una macchina affamata di memoria o quando non vengono mai utilizzati tutti gli elementi dell'intervallo (come quando il ciclo è di solito terminato conbreak
).
range crea un elenco, quindi se lo fai range (1, 10000000) crea un elenco in memoria con 10000000 elementi. xrange è un generatore, quindi valuta pigramente.
Ciò offre due vantaggi:
MemoryError
.Troverai il vantaggio di xrange
over range
in questo semplice esempio:
import timeit
t1 = timeit.default_timer()
a = 0
for i in xrange(1, 100000000):
pass
t2 = timeit.default_timer()
print "time taken: ", (t2-t1) # 4.49153590202 seconds
t1 = timeit.default_timer()
a = 0
for i in range(1, 100000000):
pass
t2 = timeit.default_timer()
print "time taken: ", (t2-t1) # 7.04547905922 seconds
L'esempio sopra non riflette nulla di sostanzialmente migliore in caso di xrange
.
Ora guarda il seguente caso in cui range
è davvero molto lento, rispetto a xrange
.
import timeit
t1 = timeit.default_timer()
a = 0
for i in xrange(1, 100000000):
if i == 10000:
break
t2 = timeit.default_timer()
print "time taken: ", (t2-t1) # 0.000764846801758 seconds
t1 = timeit.default_timer()
a = 0
for i in range(1, 100000000):
if i == 10000:
break
t2 = timeit.default_timer()
print "time taken: ", (t2-t1) # 2.78506207466 seconds
Con range
, crea già un elenco da 0 a 100000000 (che richiede tempo), ma xrange
è un generatore e genera solo numeri in base alla necessità, vale a dire se l'iterazione continua.
In Python-3, l'implementazione della range
funzionalità è la stessa di xrange
Python-2, mentre xrange
in Python-3 è stata eliminata
Buona programmazione !!
È per motivi di ottimizzazione.
range () creerà un elenco di valori dall'inizio alla fine (0 .. 20 nel tuo esempio). Questo diventerà un'operazione costosa su gamme molto grandi.
xrange () d'altra parte è molto più ottimizzato. calcolerà il valore successivo solo quando necessario (tramite un oggetto sequenza xrange) e non crea un elenco di tutti i valori come range ().
range(x,y)
restituisce un elenco di ciascun numero tra xey se si utilizza un for
ciclo, quindi range
è più lento. In effetti, range
ha una gamma di indici più ampia. range(x.y)
stamperà un elenco di tutti i numeri tra x e y
xrange(x,y)
ritorna xrange(x,y)
ma se hai usato un for
loop, allora xrange
è più veloce. xrange
ha un intervallo di indice più piccolo. xrange
non solo stamperà xrange(x,y)
ma manterrà comunque tutti i numeri che ci sono dentro.
[In] range(1,10)
[Out] [1, 2, 3, 4, 5, 6, 7, 8, 9]
[In] xrange(1,10)
[Out] xrange(1,10)
Se usi un for
loop, allora funzionerebbe
[In] for i in range(1,10):
print i
[Out] 1
2
3
4
5
6
7
8
9
[In] for i in xrange(1,10):
print i
[Out] 1
2
3
4
5
6
7
8
9
Non c'è molta differenza quando si usano i loop, anche se c'è una differenza quando si stampa!
range (): range (1, 10) restituisce un elenco da 1 a 10 numeri e mantiene l'intero elenco in memoria.
xrange (): come range (), ma invece di restituire un elenco, restituisce un oggetto che genera i numeri nell'intervallo su richiesta. Per il looping, questo è leggermente più veloce di range () e più efficiente della memoria. xrange () oggetto come un iteratore e genera i numeri su richiesta. (Valutazione pigra)
In [1]: range(1,10)
Out[1]: [1, 2, 3, 4, 5, 6, 7, 8, 9]
In [2]: xrange(10)
Out[2]: xrange(10)
In [3]: print xrange.__doc__
xrange([start,] stop[, step]) -> xrange object
Alcune delle altre risposte menzionano che Python 3 ha eliminato 2.x range
e rinominato 2.x xrange
in range
. Tuttavia, a meno che non si utilizzi 3.0 o 3.1 (che nessuno dovrebbe essere), in realtà è un tipo leggermente diverso.
Come dicono i documenti 3.1 :
Gli oggetti intervallo hanno un comportamento molto limitato: supportano solo indicizzazione, iterazione e
len
funzione.
Tuttavia, in 3.2+, range
è una sequenza completa: supporta sezioni estese e tutti i metodi collections.abc.Sequence
con la stessa semantica di a list
. *
E, almeno in CPython e PyPy (gli unici due 3.2+ implementazioni attualmente esistenti), ma ha anche implementazioni costante di tempo del index
e count
metodi e l' in
operatore (a patto che si passa solo numeri interi). Ciò significa che la scrittura 123456 in r
è ragionevole in 3.2+, mentre in 2.7 o 3.1 sarebbe un'idea orribile.
* Il fatto che issubclass(xrange, collections.Sequence)
ritorni True
in 2.6-2.7 e 3.0-3.1 è un bug che è stato corretto in 3.2 e non eseguito il backport.
In Python 2.x
range (x) restituisce un elenco, che viene creato in memoria con x elementi.
>>> a = range(5)
>>> a
[0, 1, 2, 3, 4]
xrange (x) restituisce un oggetto xrange che è un oggetto generatore che genera i numeri su richiesta. vengono calcolati durante il for-loop (Lazy Evaluation).
Per il loop, questo è leggermente più veloce di range () e più efficiente della memoria.
>>> b = xrange(5)
>>> b
xrange(5)
xrange()
non è un generatore. xrange(n)
.__ iter __ () `è.
Quando ho testato range contro xrange in un ciclo (so che dovrei usare timeit , ma questo è stato rapidamente cancellato dalla memoria usando un semplice esempio di comprensione dell'elenco) ho trovato quanto segue:
import time
for x in range(1, 10):
t = time.time()
[v*10 for v in range(1, 10000)]
print "range: %.4f" % ((time.time()-t)*100)
t = time.time()
[v*10 for v in xrange(1, 10000)]
print "xrange: %.4f" % ((time.time()-t)*100)
che dà:
$python range_tests.py
range: 0.4273
xrange: 0.3733
range: 0.3881
xrange: 0.3507
range: 0.3712
xrange: 0.3565
range: 0.4031
xrange: 0.3558
range: 0.3714
xrange: 0.3520
range: 0.3834
xrange: 0.3546
range: 0.3717
xrange: 0.3511
range: 0.3745
xrange: 0.3523
range: 0.3858
xrange: 0.3997 <- garbage collection?
Oppure, usando xrange nel ciclo for:
range: 0.4172
xrange: 0.3701
range: 0.3840
xrange: 0.3547
range: 0.3830
xrange: 0.3862 <- garbage collection?
range: 0.4019
xrange: 0.3532
range: 0.3738
xrange: 0.3726
range: 0.3762
xrange: 0.3533
range: 0.3710
xrange: 0.3509
range: 0.3738
xrange: 0.3512
range: 0.3703
xrange: 0.3509
Il mio frammento sta eseguendo correttamente il test? Qualche commento sull'istanza più lenta di xrange? O un esempio migliore :-)
xrange
sembrava leggermente più veloce, anche se con Python 3 il confronto è ora ridondante.
timeit
serve. Si occupa di eseguire molte volte, disabilitare GC, utilizzare l'orologio migliore anziché time
, ecc.
xrange () e range () in python funzionano in modo simile a quello dell'utente, ma la differenza viene quando parliamo di come viene allocata la memoria usando entrambe le funzioni.
Quando stiamo usando range () allociamo la memoria per tutte le variabili che sta generando, quindi non è consigliabile usare con no più grandi. delle variabili da generare.
xrange () d'altra parte genera solo un valore particolare alla volta e può essere utilizzato solo con il ciclo for per stampare tutti i valori richiesti.
range genera l'intero elenco e lo restituisce. xrange no: genera i numeri nell'elenco su richiesta.
Che cosa?
range
restituisce un elenco statico in fase di esecuzione.
xrange
restituisce un object
(che si comporta come un generatore, sebbene non sia certamente uno) da cui vengono generati i valori come e quando richiesto.
Quando usare quale?
xrange
se si desidera generare un elenco per un intervallo gigantesco, ad esempio 1 miliardo, soprattutto quando si dispone di un "sistema sensibile alla memoria" come un telefono cellulare.range
se si desidera scorrere più volte l'elenco.PS: di Python 3.x range
funzione == di Python 2.x xrange
funzione.
xrange
non restituisce un oggetto generatore.
Tutti lo hanno spiegato molto. Ma volevo vederlo da solo. Uso python3. Quindi, ho aperto il monitor risorse (in Windows!) E prima ho eseguito prima il comando seguente:
a=0
for i in range(1,100000):
a=a+i
e quindi ho verificato la modifica nella memoria "In uso". Era insignificante. Quindi, ho eseguito il seguente codice:
for i in list(range(1,100000)):
a=a+i
E ci volle un grosso pezzo di memoria per usarla, all'istante. E ne ero convinto. Puoi provarlo tu stesso.
Se stai usando Python 2X, sostituisci 'range ()' con 'xrange ()' nel primo codice e 'list (range ())' con 'range ()'.
Dai documenti di aiuto.
Python 2.7.12
>>> print range.__doc__
range(stop) -> list of integers
range(start, stop[, step]) -> list of integers
Return a list containing an arithmetic progression of integers.
range(i, j) returns [i, i+1, i+2, ..., j-1]; start (!) defaults to 0.
When step is given, it specifies the increment (or decrement).
For example, range(4) returns [0, 1, 2, 3]. The end point is omitted!
These are exactly the valid indices for a list of 4 elements.
>>> print xrange.__doc__
xrange(stop) -> xrange object
xrange(start, stop[, step]) -> xrange object
Like range(), but instead of returning a list, returns an object that
generates the numbers in the range on demand. For looping, this is
slightly faster than range() and more memory efficient.
Python 3.5.2
>>> print(range.__doc__)
range(stop) -> range object
range(start, stop[, step]) -> range object
Return an object that produces a sequence of integers from start (inclusive)
to stop (exclusive) by step. range(i, j) produces i, i+1, i+2, ..., j-1.
start defaults to 0, and stop is omitted! range(4) produces 0, 1, 2, 3.
These are exactly the valid indices for a list of 4 elements.
When step is given, it specifies the increment (or decrement).
>>> print(xrange.__doc__)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'xrange' is not defined
La differenza è evidente. In Python 2.x, range
restituisce un elenco, xrange
restituisce un oggetto xrange che è iterabile.
In Python 3.x range
diventa xrange
Python 2.x e xrange
viene rimosso.
Su un requisito per la scansione / stampa di articoli 0-N, range e xrange funzionano come segue.
range () - crea un nuovo elenco in memoria e prende tutti gli elementi da 0 a N (totalmente N + 1) e li stampa. xrange () - crea un'istanza iteratore che esegue la scansione degli elementi e mantiene in memoria solo l'elemento corrente rilevato, quindi utilizzando sempre la stessa quantità di memoria.
Nel caso in cui l'elemento richiesto sia in qualche modo all'inizio dell'elenco, si risparmia una buona quantità di tempo e memoria.
xrange
non crea un'istanza iteratore. Crea un xrange
oggetto, che è iterabile, ma non un iteratore, quasi (ma non del tutto) una sequenza, come un elenco.
Range restituisce un elenco mentre xrange restituisce un oggetto xrange che occupa la stessa memoria indipendentemente dalle dimensioni dell'intervallo, poiché in questo caso viene generato e disponibile un solo elemento per iterazione mentre in caso di utilizzo dell'intervallo, tutti gli elementi vengono generati contemporaneamente e sono disponibili in memoria.
La differenza diminuisce per argomenti più piccoli su range(..)
/ xrange(..)
:
$ python -m timeit "for i in xrange(10111):" " for k in range(100):" " pass"
10 loops, best of 3: 59.4 msec per loop
$ python -m timeit "for i in xrange(10111):" " for k in xrange(100):" " pass"
10 loops, best of 3: 46.9 msec per loop
In questo caso xrange(100)
è solo circa il 20% più efficiente.
range: -range popolerà tutto in una volta, il che significa che ogni numero dell'intervallo occuperà la memoria.
xrange: -xrange è qualcosa di simile al generatore, entrerà in scena quando si desidera l'intervallo di numeri ma non si desidera che vengano memorizzati, come quando si desidera utilizzarlo per la memoria di loop.so efficiente.
Inoltre, if do list(xrange(...))
sarà equivalente a range(...)
.
Quindi list
è lento.
Inoltre, in xrange
realtà non completa completamente la sequenza
Ecco perché non è un elenco, è un xrange
oggetto
range()
in Python 2.x
Questa funzione è essenzialmente la vecchia range()
funzione disponibile in Python 2.x
e restituisce un'istanza di un list
oggetto che contiene gli elementi nell'intervallo specificato.
Tuttavia, questa implementazione è troppo inefficiente quando si tratta di inizializzare un elenco con un intervallo di numeri. Ad esempio, for i in range(1000000)
sarebbe un comando molto costoso da eseguire, sia in termini di memoria che di utilizzo del tempo in quanto richiede la memorizzazione di questo elenco nella memoria.
range()
in Python 3.x
e xrange()
in Python2.x
Python ha 3.x
introdotto un'implementazione più recente di range()
(mentre l'implementazione più recente era già disponibile in Python 2.x
tramitexrange()
funzione).
Il range()
sfrutta una strategia nota come valutazione pigra. Invece di creare un vasto elenco di elementi nel raggio d'azione, l'implementazione più recente introduce la classe range
, un oggetto leggero che rappresenta gli elementi richiesti nell'intervallo dato, senza memorizzarli esplicitamente in memoria (questo potrebbe sembrare generatori ma il concetto di valutazione lenta è diverso).
Ad esempio, considerare quanto segue:
# Python 2.x
>>> a = range(10)
>>> type(a)
<type 'list'>
>>> b = xrange(10)
>>> type(b)
<type 'xrange'>
e
# Python 3.x
>>> a = range(10)
>>> type(a)
<class 'range'>
Vedi questo post per trovare la differenza tra range e xrange:
Per citare:
range
restituisce esattamente quello che pensi: un elenco di numeri interi consecutivi, di una lunghezza definita che inizia con 0.xrange
, tuttavia, restituisce un "oggetto xrange" , che agisce molto come un iteratore
xrange
non è un iteratore. L'elenco restituito da range
supporta l'iterazione (un elenco è praticamente l'esempio prototipico di un iterabile). Il vantaggio complessivo di xrange
non è "minimo". E così via.