Python 3 trasforma l'intervallo in un elenco


178

Sto cercando di fare un elenco con i numeri 1-1000al suo interno. Ovviamente questo sarebbe fastidioso da scrivere / leggere, quindi sto cercando di fare un elenco con un intervallo al suo interno. In Python 2 sembra che:

some_list = range(1,1000)

avrebbe funzionato, ma in Python 3 l'intervallo è simile a quello xrangedi Python 2?

Qualcuno può fornire alcune informazioni in merito?


1
inoltre, some_list[i] == i+1quindi probabilmente non hai davvero bisogno di un elenco comunque.
njzk2,

1
@RikPoggi. ad esempio, potrebbe essere necessario fornire un elenco per una funzione di stampa. A volte un intervallo sarà sufficiente, ma un intervallo non può essere concatenato (è immutabile), quindi se è necessario aggiungere un valore iniziale predefinito a tutti gli elenchi da tracciare, anche quello deve essere trasformato in un elenco.
SherylHohman,

Risposte:


223

Puoi semplicemente costruire un elenco dall'oggetto range:

my_list = list(range(1, 1001))

Questo è il modo in cui lo fai anche con i generatori in python2.x. In genere, probabilmente non hai bisogno di un elenco, dato che puoi ottenere il valore di in modo my_list[i]più efficiente ( i + 1) e se hai solo bisogno di iterare su di esso, puoi semplicemente ricorrere range.

Si noti inoltre che su python2.x xrangeè ancora indicizzabile 1 . Ciò significa che rangesu python3.x ha anche la stessa proprietà 2

1print xrange(30)[12] funziona per python2.x

2 L'analoga istruzione a 1 in python3.x è print(range(30)[12])e funziona anche.


4
Questa è sicuramente la strada da percorrere, ma un gioco da ragazzi: non è proprio un "cast"
jterrace

@jterrace ha cambiato "cast" in "convert". Hai ragione sul fatto che non è un cast ... Non so davvero come chiamarlo esattamente.
mgilson,

2
Direi "costruisci" o "costruisci" (o eventualmente "materializza") - poiché non stai "convertendo" (come tale) un generatore in un elenco, stai creando un nuovo oggetto elenco da un'origine dati che si verifica essere un generatore ... (ma intendo solo spaccare i capelli e non sicuro al 100% di ciò che preferisco comunque)
Jon Clements

2
Il mio +1 per "costruire" in quanto è coerente con altre lingue OO. Si list(arg)intende in altre lingue come chiamare un costruttore della listclasse. In realtà, è anche il caso Python. I dibattiti se l'oggetto viene riempito durante la costruzione (come nel caso C ++) o solo durante il primo metodo chiamato automaticamente (come nel __init__()metodo Python ) non possono cambiare l'idea astratta di base. A mio avviso, il costruttore dell'elenco prende l'iteratore e riempie l'elenco con i valori restituiti .
PEPR

2
Perché dà un errore nel notebook jupyter e funziona bene nella shell? Errore:'range' object is not callable
subtleseeker,

34

In Pythons <= 3.4 puoi, come altri hanno suggerito, usare list(range(10))per fare un elenco fuori da un intervallo (In generale, qualsiasi iterabile).

Un'altra alternativa, introdotta in Python 3.5con le sue generalizzazioni di decompressione, è usare *in un elenco letterale []:

>>> r = range(10)
>>> l = [*r]
>>> print(l)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

Anche se questo equivale a list(r), è una sintassi letterale e il fatto che non sia coinvolta alcuna chiamata di funzione consente di eseguirla più velocemente. Sono anche meno caratteri, se devi programmare il golf :-)


4
Per essere chiari, puoi ancora una riga: [*range(10)]funziona bene per quando non hai bisogno di rangeper qualsiasi scopo ma inizializzare il list. Nota a margine: la mia parte preferita (va bene, non proprio) delle generalizzazioni di disimballaggio è che i messaggi vuoti setora hanno una sintassi letterale {*()}, o come lo chiamo, l'operatore scimmia con un occhio solo. ;-)
ShadowRanger

@ShadowRanger è così che inizialmente pensavo di scriverlo. Ho deciso di essere un po 'più prolisso per non confondere i nuovi utenti di Python :-)
Dimitris Fasarakis Hilliard

26

in Python 3.x, la range()funzione ha il suo tipo. quindi in questo caso devi usare iteratore

list(range(1000))


11
"in questo caso devi usare iteratore"? Cosa diavolo dovrebbe significare?
user2357112 supporta Monica il

2
Sto usando Python 3.7 e ho provato x = list (range (1000)) ma ho ricevuto l'errore TypeError: l'oggetto 'list' non è richiamabile
Earthshaker

@Earthshaker Devi avere un refuso, comelist(range(1000))()
wjandrea il

17

Il motivo per cui Python3 non ha una funzione per ottenere direttamente un elenco a distanza è perché il designer originale di Python3 era abbastanza principiante in Python2. Ha considerato solo l'uso della range()funzione in un ciclo for, quindi l'elenco non dovrebbe mai essere ampliato. In effetti, molto spesso abbiamo bisogno di usare la range()funzione per produrre un elenco e passare a una funzione.

Pertanto, in questo caso, Python3 è meno conveniente rispetto a Python2 perché:

  • In Python2, abbiamo xrange()e range();
  • In Python3, abbiamo range()elist(range())

Tuttavia, puoi comunque utilizzare l'espansione dell'elenco in questo modo:

[*range(N)]

3
Il punto è rendere meno conveniente fare un list, perché di solito è la cosa sbagliata da fare. Per 99 casi d'uso su 100, rendere un effettivo listè inefficiente e inutile, dal momento che rangesi comporta come una sequenza immutabile in quasi tutti i modi, a volte in modo più efficiente per l'avvio (ad es. Test di contenimento per ints sono O(1), contro O(n)per lists). In Python 2, le persone tendevano a usare rangedi default, anche se xrangequasi sempre era l'opzione migliore; in Python 3, puoi esplicitamente optare per il list, non ottenerlo per caso usando il nome sbagliato.
ShadowRanger,

7
Il commento sul designer Python 3 e la sua esperienza in Python 2 è piuttosto audace e impertinente.
Kazarey,

@kazarey Ma è vero? Ci sono molte cose in Python che sono discutibili in questo senso
javadba,

1
Voterei, soprattutto per la stenografia unpacking per costruire l'elenco, ma sono d'accordo con @kazarey. Il commento sul designer è sia infondato (o almeno non supportato da riferimenti) e non necessario.
Nubarke,

12

Non dovresti davvero usare i numeri 1-1000 in un elenco. Ma se per qualche motivo hai davvero bisogno di questi numeri, allora potresti fare:

[i for i in range(1, 1001)]

Elenco completo in breve:

La comprensione dell'elenco precedente si traduce in:

nums = []
for i in range(1, 1001):
    nums.append(i)

Questa è solo la sintassi di comprensione dell'elenco, sebbene da 2.x. So che funzionerà in Python 3, ma non sono sicuro che esista anche una sintassi aggiornata

L'intervallo inizia compreso il primo parametro; ma finisce fino a, senza includere il secondo parametro (se fornito 2 parametri; se il primo parametro viene lasciato fuori, inizierà da '0')

range(start, end+1)
[start, start+1, .., end]

20
Perché comprensione? Solo:list(range(1000))
Rik Poggi,

Grazie! Ti dispiacerebbe spiegare perché sono io per me in ... anziché semplicemente per me in?
Rimessa per

Non ho lavorato con python3. Quindi non sono del tutto sicuro di come funzioni. So che le comprensioni funzioneranno, ma non erano al 100% sul casting. Ma se il casting funziona, allora hai ragione e la tua strada è più pitonica.
inspectorG4dget,

1
@ inspectorG4dget: non è "casting", ma chiama il list()costruttore con un iterabile . Il list()costruttore sa come creare un nuovo elenco quando viene assegnato qualsiasi oggetto iterabile.
Greg Hewgill,

4
@ inspectorG4dget: list(range(1000))funzionerà in python3 proprio come list(xrange(1000))in python2
Rik Poggi

4

In realtà, se si desidera 1-1000 (incluso), utilizzare la range(...)funzione con i parametri 1 e 1001 :, range(1, 1001)poiché la range(start, end)funzione va dall'inizio alla (fine-1), incluso.


0

Usa Range in Python 3.

Ecco una funzione di esempio che ritorna tra i numeri da due numeri

def get_between_numbers(a, b):
    """
    This function will return in between numbers from two numbers.
    :param a:
    :param b:
    :return:
    """
    x = []
    if b < a:
        x.extend(range(b, a))
        x.append(a)
    else:
        x.extend(range(a, b))
        x.append(b)

    return x

Risultato

print(get_between_numbers(5, 9))
print(get_between_numbers(9, 5))

[5, 6, 7, 8, 9]  
[5, 6, 7, 8, 9]

Questo sembra rispondere a una domanda diversa ...?
wjandrea,

-1

In realtà, questa è una retro-gradazione di Python3 rispetto a Python2. Certamente, Python2 che usa range () e xrange () è più conveniente di Python3 che usa rispettivamente list (range ()) e range (). Il motivo è che il progettista originale di Python3 non ha molta esperienza, ha considerato l'uso della funzione range solo da molti principianti per iterare su un gran numero di elementi in cui la memoria e la CPU sono inefficienti; ma hanno trascurato l'uso della funzione range per produrre un elenco di numeri. Ora è troppo tardi perché tornino indietro.

Se dovessi essere il designer di Python3, dovrei:

  1. usa irange per restituire un iteratore di sequenza
  2. utilizzare lrange per restituire un elenco di sequenze
  3. usa range per restituire un iteratore di sequenza (se il numero di elementi è grande, ad esempio range (9999999) o un elenco di sequenze (se il numero di elementi è piccolo, ad esempio range (10))

Questo dovrebbe essere ottimale.


Come risponde alla domanda?
wjandrea,

Sì, risponde alla domanda chiedendo agli sviluppatori di Python3 di cambiare e migliorare Python3. Ma è improbabile che cambieranno perché non sono così eleganti.
xuancong84
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.