Come creare una lista con una dimensione specifica in Python

  1. Preallocazione della memoria per le liste
  2. Preallocazione della memorizzazione per altre strutture di dati sequenziali

La preallocazione della memoria per liste o array è uno schema tipico tra i programmatori quando conoscono il numero di elementi in anticipo.

A differenza di C+++ e Java, in Python, si deve inizializzare tutta la memoria preassegnata con alcuni valori. Di solito, gli sviluppatori usano valori falsi per questo scopo, come None, '', False, e 0.

Python offre diversi modi per creare una lista di dimensioni fisse, ciascuno con caratteristiche di prestazione diverse.

Per confrontare le prestazioni dei diversi approcci, useremo lo standard Python modulo timeit. Fornisce un modo pratico per misurare i tempi di esecuzione di piccoli pezzi di codice Python.

Preallocazione della memoria per le liste

Il primo e più veloce modo di usare l’operatore *, che ripete una lista di un determinato operatore numero di volte.

>>> [None] * 10
[None, None, None, None, None, None, None, None, None, None]

Un milione di iterazioni (valore predefinito delle iterazioni in timeit) richiede circa 117 ms.

>>> timeit("[None] * 10")
0.11655918900214601

Un altro approccio è quello di utilizzare la funzione integrata range con una comprensione della lista.

>>> [None for _ in range(10)]
[None, None, None, None, None, None, None, None, None, None]

E’ quasi sei volte più lenta e richiede 612 ms al secondo per milione di iterazioni.

>>> timeit("[None for _ in range(10)]")
0.6115895550028654

Il terzo approccio è quello di usare un semplice ciclo for insieme alla list.append().

>>> a = []
>>> for _ in range(10):
...   a.append(None)
...
>>> a
[None, None, None, None, None, None, None, None, None, None]

L’utilizzo di loop è il metodo più lento e richiede 842 ms per completare un milione di iterazioni.

>>> timeit("for _ in range(10): a.append(None)", setup="a=[]")
0.8420009529945673

Preallocazione della memorizzazione per altre strutture di dati sequenziali

Dal momento che si sta preallocando la memorizzazione per una struttura di dati sequenziale, può avere molto senso utilizzare la struttura dei dati incorporata array invece di una lista.

>>> from array import array
>>> array('i',(0,)*10)
array('i', [0, 0, 0, 0, 0, 0, 0, 0, 0, 0])

Come vediamo qui di seguito, questo approccio è il secondo più veloce dopo [None] * 10.

>>> timeit("array('i',(0,)*10)", setup="from array import array")
0.4557597979946877

Confrontiamo gli approcci Python puro di cui sopra con il pacchetto NumPy Python per il calcolo scientifico.

>>> from numpy import empty
>>> empty(10)
array([0., 0., 0., 0., 0., 0., 0., 0., 0., 0.])

Il metodo NumPy richiede 589 ms per milione di iterazioni.

>>> timeit("empty(10)", setup="from numpy import empty")
0.5890094790011062

Tuttavia, il metodo NumPy sarà molto più veloce per liste più massicce.

>>> timeit("[None]*10000")
16.059584009999526
>>> timeit("empty(10000)", setup="from numpy import empty")
1.1065983309963485

La conclusione è che è meglio attenersi a [None] * 10 per le piccole liste, ma cambiare al empty() di NumPy quando si tratta di dati sequenziali più massicci.

Articolo correlato - Python List

  • Crea una lista di liste in Python
  • Aggiungi un elenco a un set in Python