Stampa un elenco in ordine inverso con range ()?


364

Come puoi produrre il seguente elenco con range()in Python?

[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]

Che dire di [* range (9, -1, -1)]? Super pythonic!
onofricamila,

Risposte:


561

utilizzare la reversed()funzione:

reversed(range(10))

È molto più significativo.

Aggiornare:

Se vuoi che sia un elenco (come sottolineato da BTK):

list(reversed(range(10)))

Aggiornare:

Se si desidera utilizzare solo rangeper ottenere lo stesso risultato, è possibile utilizzare tutti i suoi parametri.range(start, stop, step)

Ad esempio, per generare un elenco [5,4,3,2,1,0], è possibile utilizzare quanto segue:

range(5, -1, -1)

Potrebbe essere meno intuitivo, ma come menzionano i commenti, questo è più efficiente e il corretto utilizzo dell'intervallo per l'elenco invertito.


13
Sebbene sia "meno" efficiente. E non puoi eseguire operazioni di slicing su di esso.
Jakob Bowyer,

6
Questa risposta è molto chiara e facile da capire, ma deve essere range(10)no range(9). Inoltre, se si desidera un elenco completo (per tagliare, ecc.), È necessario farlo list(reversed(range(10))).
John Y,

5
Questo produce un iteratore, OP ha chiesto un risultato sotto forma di un elenco.
proposito il

6
L'uso di "inverso" con il generatore Python (supponendo che stiamo parlando della gamma Python 3 integrata) è concettualmente sbagliato e insegna abitudini sbagliate a non considerare la complessità della memoria / elaborazione durante la programmazione in un linguaggio di alto livello.
pubblicato il

7
In Python3, reversednon accetta generatori in generale ma accetta range. Perché dovrebbe essere reversed(range(10000))necessario allocare memoria per l'intero elenco? rangepuò restituire un oggetto che implementa il __reversed__metodo che consente un'iterazione inversa efficiente?
avmohan,

312

Utilizzare la funzione integrata 'range'. La firma è range(start, stop, step). Questo produce una sequenza che produce numeri, iniziando con starte terminando se stopè stata raggiunta, escluso stop.

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

In Python 3, questo produce un rangeoggetto non-list , che funziona efficacemente come un elenco di sola lettura (ma usa molta meno memoria, in particolare per intervalli di grandi dimensioni).


1
Puoi per favore spiegare anche questo, per favore, mi puoi consigliare qualsiasi sito web / libro pdf per Python
ramesh.mimit

8
@ramesh Se corri help(range)in una shell Python ti dirà gli argomenti. Sono il numero su cui iniziare, il numero su cui terminare (esclusivo) e il passo da compiere, quindi inizia da 9 e sottrae 1 fino a raggiungere -1 (a quel punto si ferma senza ritornare, motivo per cui l'intervallo termina a 0)
Michael Mrozek,

3
@ ramesh.mimit: vai sul sito ufficiale di Python. C'è una documentazione completa lì, incluso un ottimo tutorial.
John Y,

5
Davvero, questa è la risposta corretta, ma potrebbe essere spiegata più chiaramente. range(start, stop, step) - iniziare dal numero starte produrre risultati se non stopè stato raggiunto, spostandosi di stepvolta in volta.
Mr. B,

43

Puoi usare range(10)[::-1]qual è la stessa cosa range(9, -1, -1)e probabilmente più leggibile (se hai familiarità con il sequence[::-1]linguaggio comune di Python).


28

Per coloro che sono interessati all '"efficienza" delle opzioni finora raccolte ...

La risposta di Jaime RGP mi ha portato a riavviare il computer dopo temporizzazione la soluzione un po ' "sfida" di Jason letteralmente seguito il mio suggerimento (via commento). Per risparmiare ai tuoi curiosi i tempi di fermo, ti presento i miei risultati (il peggiore per primi):

La risposta di Jason (forse solo un'escursione nel potere della comprensione della lista ):

$ python -m timeit "[9-i for i in range(10)]"
1000000 loops, best of 3: 1.54 usec per loop

La risposta di martineau (leggibile se si ha familiarità con la sintassi delle sezioni estese ):

$ python -m timeit "range(10)[::-1]"
1000000 loops, best of 3: 0.743 usec per loop

La risposta di Michał Šrajer (quella accettata, molto leggibile):

$ python -m timeit "reversed(range(10))"
1000000 loops, best of 3: 0.538 usec per loop

la risposta di Bene (la prima, ma molto approssimativa in quel momento ):

$ python -m timeit "range(9,-1,-1)"
1000000 loops, best of 3: 0.401 usec per loop

L'ultima opzione è facile da ricordare usando la range(n-1,-1,-1)notazione di Val Neekman .


3
Ho fatto i miei tempi prima di leggere questa risposta e ho ottenuto gli stessi risultati.
Todd Owen,

13
for i in range(8, 0, -1)

risolverà questo problema. Produrrà da 8 a 1 e -1 indica un elenco invertito


10

Non ha senso utilizzare reverseperché il metodo range può restituire un elenco invertito.

Quando si ha iterazione su n elementi e si desidera sostituire l'ordine dell'elenco restituito, range(start, stop, step)è necessario utilizzare il terzo parametro dell'intervallo che lo identifica stepe impostarlo su -1, altri parametri devono essere adeguati di conseguenza:

  1. Fornire il parametro stop as -1(il valore precedente di stop - 1, stopera uguale a 0).
  2. Come parametro iniziale utilizzare n-1.

Quindi l'equivalente dell'intervallo (n) in ordine inverso sarebbe:

n = 10
print range(n-1,-1,-1) 
#[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]

6
Francamente lo trovo meno intuitivo direversed(range(n))
Nicholas Hamilton l'

1
@NicholasHamilton Concordo con te, tuttavia l'idea alla base di quella risposta è quella di utilizzare meno risorse ... (e la domanda era sull'utilizzo della funzione di solo intervallo :))
Andriy Ivaneyko,

Ok, non preoccuparti, immagino che dipenda dalla situazione. Ad esempio, se la funzione range viene utilizzata come indice per un loop, avrà un effetto limitato, tuttavia, se viene utilizzata all'interno di un loop esterno, il costo sarà composto ...
Nicholas Hamilton

8

Leggibilità a parte, reversed(range(n))sembra essere più veloce di range(n)[::-1].

$ python -m timeit "reversed(range(1000000000))"
1000000 loops, best of 3: 0.598 usec per loop
$ python -m timeit "range(1000000000)[::-1]"
1000000 loops, best of 3: 0.945 usec per loop

Solo se qualcuno si chiedeva :)


bello avere dei numeri :) - perché non l'hai aggiunto anche tu range(1000000000-1,-1,-1)?
Lupo,

... meglio non provare timeit range(1000000000-1,-1,-1)dalla riga di comando, invece vedi i miei risultati :-)
Wolf

6

Il requisito in questa domanda richiede un numero listintero di dimensione 10 in ordine decrescente. Quindi, produciamo un elenco in Python.

# This meets the requirement.
# But it is a bit harder to wrap one's head around this. right?
>>> range(10-1, -1, -1)
[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]

# let's find something that is a bit more self-explanatory. Sounds good?
# ----------------------------------------------------

# This returns a list in ascending order.
# Opposite of what the requirement called for.
>>> range(10)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

# This returns an iterator in descending order.
# Doesn't meet the requirement as it is not a list.
>>> reversed(range(10))
<listreverseiterator object at 0x10e14e090>

# This returns a list in descending order and meets the requirement
>>> list(reversed(range(10)))
[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]

2
Mi piace molto il triplo-1 È esattamente questo modello che lo rende facile da mantenere wrap one's head around this- Oggi ho imparato che se deve davvero essere efficiente , utilizzare range(n-1, -1, -1)quando si percorre una gamma in ordine inverso.
Lupo,

5

Puoi eseguire la stampa di numeri inversi con range () BIF Come,

for number in range ( 10 , 0 , -1 ) :
    print ( number ) 

L'output sarà [10,9,8,7,6,5,4,3,2,1]

range () - range (inizio, fine, incremento / decremento) dove inizio è inclusivo, fine è esclusiva e l'incremento può essere qualsiasi numero e si comporta come un passo


5

Molto spesso la domanda è se sia range(9, -1, -1)meglio che reversed(range(10))in Python 3? Le persone che hanno lavorato in altre lingue con iteratori tendono immediatamente a pensare che reversed () debba memorizzare nella cache tutti i valori e quindi tornare in ordine inverso. Il fatto è che l' reversed()operatore di Python non funziona se l'oggetto è solo un iteratore. L'oggetto deve avere uno dei due seguenti per reverse () per funzionare:

  1. Supporto len()e indici interi tramite[]
  2. O hanno __reversed__()implementato il metodo.

Se provi a usare reverse () su un oggetto che non ha nessuno dei precedenti, otterrai:

>>> [reversed((x for x in range(10)))]
TypeError: 'generator' object is not reversible

Quindi, in breve, Python reversed()si intende solo su array come oggetti e quindi dovrebbe avere le stesse prestazioni dell'iterazione diretta.

Ma che dire range()? Non è un generatore? In Python 3 è un generatore ma racchiuso in una classe che implementa entrambi i precedenti. Quindi range(100000)non occupa molta memoria ma supporta comunque l'indicizzazione e l'inversione efficienti.

Quindi, in sintesi, è possibile utilizzare reversed(range(10))senza alcun impatto sulle prestazioni.


3

credo che questo possa aiutare,

range(5)[::-1]

sotto è l'uso:

for i in range(5)[::-1]:
    print i 

3
range(9,-1,-1)
[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]

13
La tua risposta mostra perché reversed(range(10))è meno soggetta a errori. Senza offesa Asinox. Solo un'osservazione onesta.
Michał Šrajer,

Non so se è standard lasciare sul display risposte errate. Posso o qualcuno correggerlo o addirittura rimuoverlo?
sinekonata,

3
@sine, no, lascialo e mi chiedo come abbia accumulato 3 voti ... Suppongo che potresti segnalarlo per l'attenzione del moderatore (duplicato della risposta di 18 mesi prima tranne rotto), non sono sicuro se lo eliminerebbero o meno.
OGHaza,

Per tutti i riferimenti futuri: solo il codice non è VLQ e neanche le risposte errate devono essere contrassegnate . Downvote e vai avanti, ma in questo caso la segnalazione è sbagliata, sia NAA che mod-flagging. - Dalla recensione
Zoe,

2

Utilizzo senza [:: - 1] o invertito -

def reverse(text):
    result = []
    for index in range(len(text)-1,-1,-1):
        c = text[index]
        result.append(c)
    return ''.join(result)

print reverse("python!")

6
Perché qualcuno dovrebbe scrivere questo invece di "python!"[::-1]?
Daniel,

1
[9-i for i in range(10)]
[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]

1

Non devi necessariamente usare la funzione range, puoi semplicemente fare list [:: - 1] che dovrebbe riportare rapidamente la lista in ordine inverso, senza usare alcuna aggiunta.


Questa sembra essere la soluzione suggerita in una risposta precedente . Sembra anche che potresti provare a commentare una risposta precedente diversa: dovrai ottenere un po 'più di reputazione prima di poterlo fare.
Grisha Levit,

1

Supponi di avere un elenco chiamalo a = {1,2,3,4,5} Ora se vuoi stampare l'elenco al contrario, usa semplicemente il seguente codice.

a.reverse
for i in a:
   print(i)

So che hai chiesto di usare range ma ha già risposto.


0
range(9,-1,-1)
    [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]

È la forma corretta. Se usi

reversed(range(10))

non otterrai un caso 0. Ad esempio, supponi che il tuo 10 non sia un numero magico e una variabile che stai utilizzando per la ricerca inizi dal retro. Se il tuo n caso è 0, inverso (range (0)) non verrà eseguito, il che è sbagliato se per caso hai un singolo oggetto nell'indice zero.


0

Ho pensato che molti (come me stesso) potrebbero essere più interessati a un caso comune di attraversamento di un elenco esistente in ordine inverso, invece, come indicato nel titolo, piuttosto che generare semplicemente indici per tale attraversamento.

Anche se, tutte le risposte giuste sono ancora perfettamente valide per questo caso, voglio sottolineare che il confronto delle prestazioni fatto nella risposta di Wolf è solo per la generazione di indici. Quindi ho fatto benchmark simili per attraversare un elenco esistente in ordine inverso.

TL; DR a[::-1] è il più veloce.

Prerequisiti:

a = list(range(10))

La risposta di Jason :

%timeit [a[9-i] for i in range(10)]
1.27 µs ± 61.5 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

la risposta di martineau :

%timeit a[::-1]
135 ns ± 4.07 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)

La risposta di Michał Šrajer :

%timeit list(reversed(a))
374 ns ± 9.87 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

la risposta di bene :

%timeit [a[i] for i in range(9, -1, -1)]
1.09 µs ± 11.1 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

Come vedi, in questo caso non è necessario generare esplicitamente indici, quindi il metodo più veloce è quello che fa meno azioni extra.

NB: ho provato su JupyterLab che ha un pratico "comando magico" %timeit. Utilizza standard timeit.timeitsotto il cofano. Testato per Python 3.7.3

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.