Uno strumento per produrre numeri
range() fa esattamente una cosa: produce una sequenza di interi. È il compagno ideale dei cicli for quando devi ripetere qualcosa un numero preciso di volte o percorrere un intervallo numerico.
La forma più semplice accetta un solo argomento, il valore di stop:
Output:
0
1
2
3
4
Due dettagli che colgono di sorpresa chi inizia:
- Si comincia a contare da 0.
range(5)ti dà cinque numeri, a partire da 0. - Il valore di stop è escluso.
range(5)si ferma prima del 5: non include il 5 stesso.
Queste regole sono coerenti in tutte le operazioni di slicing, indicizzazione e range di Python. Una volta interiorizzato che "lo stop è escluso", smette di crearti problemi.
Tre forme
range() accetta uno, due o tre argomenti:
Lo step è l'ampiezza di ogni salto. range(0, 20, 4) produce un numero ogni quattro. Tienilo a mente la prossima volta che ti serve "un elemento sì e uno no" o "un campione ogni dieci".
Contare all'indietro
Lo step può essere negativo, e questo ti permette di contare all'indietro:
Anche qui lo stop è escluso: range(10, 0, -1) si ferma prima dello 0, non sullo 0. Per includere lo 0, metti lo stop a -1:
range è pigro
In Python 3, range() non costruisce in memoria una lista di numeri. Restituisce un oggetto range leggero che produce i numeri uno alla volta, su richiesta. Per questo puoi scrivere:
Un "range" da un miliardo di numeri non occupa praticamente memoria. I numeri vengono generati man mano che il ciclo li chiede.
Se ti serve davvero una lista dei numeri, perché vuoi modificarla, ordinarla o indicizzarla oltre le basi, convertila esplicitamente:
Il più delle volte la lista non ti serve. for i in range(...) funziona direttamente.
Schemi comuni
Qualche ricetta che userai di continuo:
Fare qualcosa n volte.
_ è una convenzione che significa "questo valore non mi interessa": Python non la impone, ma chiunque legga capirà l'intenzione.
Indicizzare una sequenza.
Preferisci enumerate() a range(len(...)), ma quando ti serve proprio solo l'indice:
Comunque, nella maggior parte dei casi enumerate(items) è più pulito.
Scorrere un elemento sì e uno no.
Stampa a, c, e. Per uno slicing semplice, però, la sintassi dello slicing è ancora più diretta: items[::2].
Generare al volo una lista di numeri.
Questa è una list comprehension, di cui parleremo più avanti, ma è range a fornire i numeri.
Cosa range() non è
Due spigoli da conoscere:
rangeproduce solo interi. Se ti servono passi in virgola mobile (per esempio da 0.0 a 1.0 con incrementi di 0.1), usanumpy.arangeoppure un ciclo con un tuo contatore.rangenon funziona con iterabili qualsiasi. È pensato apposta per gli interi. Se stai cercando di usare "range" su una lista, probabilmente ti serveenumerateo semplicemente la lista stessa.
Mettiamo tutto insieme
Un piccolo esempio che usa diverse varianti in un colpo solo:
Due cicli annidati guidati da range che producono una griglia. Nota che entrambi i cicli partono da 1, con range(1, 6), perché vogliamo etichette da 1 a 5.
Verso le collezioni
Ora hai visto le condizioni, entrambi i tipi di ciclo e range. È un controllo di flusso sufficiente per gestire qualsiasi collezione. Prossimo capitolo: le collezioni vere e proprie, cioè liste, tuple, set e dizionari.
Domande frequenti
Cosa fa range() in Python?
range() produce una sequenza di interi. range(n) dà i numeri da 0 a n-1. range(start, stop) dà gli interi da start fino a stop escluso. range(start, stop, step) ti permette di scegliere l'ampiezza del passo, anche negativa per contare all'indietro.
range() crea una lista?
No. In Python 3, range() restituisce un oggetto range leggero che genera i numeri su richiesta. Ecco perché range(10**9) è istantaneo: non alloca davvero un miliardo di interi. Avvolgilo in list(...) se ti serve davvero una lista.
Come faccio un conto alla rovescia con range() in Python?
Usa uno step negativo: range(10, 0, -1) conta 10, 9, 8, ..., 1. Ricorda che il valore di stop è sempre escluso, quindi per includere lo 0 ti servirebbe range(10, -1, -1).