2015-07-05 8 views

risposta

33

In Python 3.x,

range(0,3) restituisce una classe di oggetti iterabili immutabili che consente di eseguire iterazioni su di loro, non produce gli elenchi, e non conservare tutti gli elementi della gamma in memoria, invece producono gli elementi al volo (mentre li stai iterando), mentre list(range(0,3)) produce un elenco (iterando su tutti gli elementi e aggiungendo l'elenco internamente).

Esempio -

>>> range(0,3) 
range(0, 3) 
>>> list(range(0,3)) 
[0, 1, 2] 

Idealmente, se si desidera solo iterare su tale intervallo di valori, range(0,3) sarebbe più veloce di (list(range(0,3)) perché quest'ultimo ha l'overhead di produrre un elenco prima di iniziare l'iterazione su di esso.

In Python 2.x, range(0,3) produce un elenco, invece abbiamo avuto anche una funzione xrange() che ha un comportamento simile range() funzione da Python 3.x (xrange stato rinominato variare in Python 3.x)

per Python 3.5, Dalle documentation -

oggetti Range attuare il collections.abc.Sequence ABC, e fornire caratteristiche come test di contenimento, ricerca di indice, affettamento e il supporto per gli indici negativi

Così si può fare le cose come -

>>> range(0,10)[5] 
5 
>>> range(0,10)[3:7] 
range(3, 7) 
>>> 5 in range(6,10) 
False 
>>> 7 in range(1,8) 
True 

E tutto si tratta di operazioni a tempo costante, come si può vedere da questa prova -

In [11]: %timeit a = xrange(0,1000000)[1000] 
1000000 loops, best of 3: 342 ns per loop 

In [12]: %timeit a = xrange(0,1000000)[10000] 
1000000 loops, best of 3: 342 ns per loop 

In [13]: %timeit a = xrange(0,1000000)[100000] 
1000000 loops, best of 3: 342 ns per loop 

In [14]: %timeit a = xrange(0,1000000)[999999] 
1000000 loops, best of 3: 342 ns per loop 

In [15]: %timeit a = xrange(0,10000000)[9999999] 
1000000 loops, best of 3: 339 ns per loop 

In [16]: %timeit a = xrange(0,1000000000000)[9999999999] 
1000000 loops, best of 3: 341 ns per loop 
+0

Quindi in Python 3 è 'range (x, y)' qualcosa di simile a un generatore? Solo qualcosa che mi stavo chiedendo da quando ho visto questo comportamento ... – Kyrubas

+0

Intenzionale per ora, perché l'interprete online che ho usato per ottenere l'esempio timeit è Python 2.7, quindi ho usato xrange invece di range. Ma non dovrebbe avere importanza perché il range di Python 3 è Python 2.x's xrange() –

+0

Ok ho pensato che fosse qualcosa del genere. Volevo solo assicurarmi che fosse intenzionale. – Scott

12

Dipende dalla versione di Python che si sta utilizzando.

In Python 2.x, range() restituisce un elenco, quindi sono equivalenti.

In Python 3.x, restituisce un tipo di sequenza immutabile, è necessario list(range(0,2)) per ottenere un elenco.

+4

In realtà "intervallo" non restituisce un generatore, è un oggetto immutabile. Prova a fare 'next (range (0,5))'. Capirai. –

+0

@AnandSKumar Correggere ora. –

1

In python3.x, gamma ha il suo type

>>> range(1) 
range(0, 1) 
>>> type(range(1)) 
<class 'range'> 

Quindi se si desidera utilizzare range() in un ciclo for, è corretto. Tuttavia non è possibile utilizzarlo purely come oggetto elenco. Devi convertirlo in lista per farlo.

python2 Esempio:

>>> L = range(10) 
>>> L[::-1] 
[9, 8, 7, 6, 5, 4, 3, 2, 1, 0] 

python3 Esempio:

>>> L = range(10) 
>>> L[::-1] 
range(9, -1, -1) 
+1

È possibile suddividere un intervallo -> >>> intervallo (0,3) [1: 3] intervallo (1, 3) ' –

+0

Come @AnandSKumar indica nella sua risposta, python3' range() 'è un tipo di sequenza e ha le stesse operazioni di liste e tuple (eccetto concat e ripetizione) https://docs.python.org/3/library/stdtypes.html#sequence-types-list-tuple-range – Scott

+0

@Anand, hai ragione su l'affettatura che funziona su di esso. Ho aggiornato la mia risposta su cosa intendevo. Grazie! –

2

Entrambi i comandi lista tornare in python2.X. Ma nell'intervallo Python3.x è una sequenza immutabile e non viene restituita la lista. Viene utilizzato per iterazioni cicli di annunci

1

Fondamentalmente, la differenza è che range(0, 2) è una funzione di generatore e list(range(0, 2)) è un elenco effettivo.

Una funzione generatore viene utilizzata nei loop. Ad esempio, una funzione di generatore di un file leggerà un file molto grande riga per riga.

def gen(): 
    for line in open("hugefile.csv", "r"): 
     yield line #Gives back the line every time it is read, but forgets that line after 

for line in gen(): 
    print(line) 

questo stampa ogni linea senza sovraccaricare la RAM del computer perché si sta solo leggendo uno per uno in entrambe le funzioni. Tuttavia, se facciamo qualcosa come

def readEntireFile(): 
    return [line for line in open("hugefile.csv", "r")] #Python has lazy ways of making lists, this is the same as returning a list with all the lines in the file 

for line in readEntireFile(): 
    print(line) 

La seconda parte sembra la stessa, ma non lo è. Originariamente, stavamo collegando su ogni riga del file e passando alla riga successiva una volta che avevamo finito con esso. Qui Python ha una lista di TUTTE le linee: /, immagina di farlo con un file da 10 GB! Il tuo codice si bloccherebbe.

Ora, torniamo al campo() e la lista (range())

Facendo for x in range(0, 6): ci fa andare al numero successivo nella gamma e completamente dimenticare il precedente (grammatica vite).

Tuttavia, facendo for x in list(range(0, 6)): mantiene l'intero elenco dei numeri nella memoria ed è lo stesso di fare

numlist = [x for x in range(6)] 
for x in numlist: 
    print(x) 

Quando è necessario l'intero elenco dei dati nel codice, utilizzare il metodo lista. Ma quando hai bisogno di un solo pezzo di dati alla volta (esempio più semplice, copia un file in blocchi), usa una funzione generatore per risparmiare spazio. È possibile copiare ogni 1 milione di righe di un file utilizzando solo 54 mb (presupponendo che non si abbiano linee follemente lunghe). Tuttavia, se abbiamo un piccolo file da 2kb, possiamo semplicemente copiare quella cosa senza un generatore. Non ne vale la pena ed è più lento in questo caso.

Problemi correlati