Python List vs. Array: quando utilizzarlo?


375

Se stai creando un array 1d, puoi implementarlo come Elenco, oppure utilizzare il modulo 'array' nella libreria standard. Ho sempre usato gli elenchi per array 1d.

Qual è la ragione o la circostanza in cui vorrei utilizzare invece il modulo array?

È per l'ottimizzazione delle prestazioni e della memoria o mi manca qualcosa di ovvio?

Risposte:


438

Fondamentalmente, gli elenchi di Python sono molto flessibili e possono contenere dati arbitrari completamente eterogenei e possono essere aggiunti in modo molto efficiente, a tempo costante ammortizzato . Se hai bisogno di restringere e far crescere la tua lista in modo efficiente e senza problemi, sono la strada da percorrere. Ma usano uno spazio molto più di matrici C .

Il array.arraytipo, d'altra parte, è solo un involucro sottile sulle matrici C. Può contenere solo dati omogenei, tutti dello stesso tipo e quindi utilizza solo sizeof(one object) * lengthbyte di memoria. Principalmente, è necessario utilizzarlo quando è necessario esporre un array C a un interno o una chiamata di sistema (ad esempio ioctlo fctnl).

array.arrayè anche un modo ragionevole per rappresentare una stringa mutabile in Python 2.x ( array('B', bytes)). Tuttavia, Python 2.6+ e 3.x offre una stringa di byte mutabile come bytearray.

Tuttavia, se vuoi fare matematica su una matrice omogenea di dati numerici, allora stai molto meglio usando NumPy, che può vettorializzare automaticamente le operazioni su matrici multidimensionali complesse.

Per farla breve : array.arrayè utile quando è necessario un array di dati C omogeneo per motivi diversi dalla matematica .


9
Numpy.ndarray ha lo stesso footprint di memoria di array.array?
Gordon Bean,

6
@Gordon, dovrebbe essere molto simile nel caso di un array grande e contiguo: entrambi richiedono sizeof(element)× (numero di elementi) byte, oltre a una piccola intestazione fissa per l'overhead. Tuttavia, ndarray ha alcune opzioni avanzate per gestire array non contigui e sparsi, e penso che alcune strategie collegabili per allocare memoria per array di grandi dimensioni ... alcune di queste funzionalità avanzate renderanno all'utente meno memoria, mentre altre miglioreranno le prestazioni usando più memoria.
Dan Lenski,

Utile anche quando la memoria è un problema, ad esempio durante la programmazione di microcontrollori con micropython
janscas,

Si può cercare l'i-esimo elemento di un array in un tempo costante, mentre nell'elenco collegato, prende l'ordine 'n' nel caso peggiore. Qual è il tempo di ricerca del mio elemento in un elenco Python?
Nithish Inpursuit Ofhappiness,

7
@NithishInpursuitOfhappiness, un elenco Python non è un elenco collegato. È rappresentato internamente come un array e presenta le stesse caratteristiche di complessità temporale dell'ArrayList di Java. Pertanto, ottenere e impostare l'i-esimo elemento di un elenco Python richiede tempo costante . L'aggiunta di un elemento a un elenco Python richiede un tempo costante ammortizzato perché la dimensione dell'array viene raddoppiata quando si esaurisce lo spazio. L'inserimento o la rimozione di un elemento dal centro di un elenco Python richiede tempo O (n) perché gli elementi devono essere spostati. Per riferimento, vedere: wiki.python.org/moin/TimeComplexity
geofflee

66

Per quasi tutti i casi l'elenco normale è la scelta giusta. Il modulo array è più simile a un wrapper sottile su array C, che ti dà una sorta di contenitori fortemente tipizzati (vedi documenti ), con accesso a più tipi simili a C come firmati / non firmati corti o doppi, che non fanno parte della build -in tipi. Direi che usa il modulo array solo se ne hai davvero bisogno, in tutti gli altri casi mantieni le liste.


3
Possibile, non l'ho mai usato davvero, ma sarebbe interessante eseguire alcuni micro benchmark.
André,

13
In realtà, ho fatto un test rapido: ho cronometrato sommando un elenco con 100 milioni di voci e lo stesso test con l'array corrispondente, e l'elenco era in realtà circa il 10% più veloce.
Moe,

38
Gli elenchi sono più veloci, poiché le operazioni sui dati "grezzi" dell'array devono creare e distruggere continuamente oggetti Python durante la lettura o la scrittura sull'array.
martedì

7
@Moe, come ho sottolineato nella mia risposta sopra, il built-in di Python nonarray è pensato per fare matematica . Se provi NumPy ndarrayper sommare un array di 10 ^ 8 numeri, esploderà completamente list. @tzot ha la giusta idea del perché l'integrato arrayè lento per la matematica.
Dan Lenski,

2
L'ho appena provato, numpy è 86.6x più veloce sulla mia macchina.
Segna il

53

Il modulo array è una di quelle cose di cui probabilmente non hai bisogno se non sai perché dovresti usarlo (e prendi nota che non sto cercando di dirlo in modo condiscendente!) . Il più delle volte, il modulo array viene utilizzato per interfacciarsi con il codice C. Per darti una risposta più diretta alla tua domanda sulle prestazioni:

Le matrici sono più efficienti delle liste per alcuni usi. Se è necessario allocare un array che SAPERE non cambierà, gli array possono essere più veloci e utilizzare meno memoria. GvR ha un aneddoto di ottimizzazione in cui il modulo array risulta essere il vincitore (lunga lettura, ma ne vale la pena).

D'altra parte, parte del motivo per cui gli elenchi consumano più memoria degli array è perché python alloca alcuni elementi extra quando vengono utilizzati tutti gli elementi allocati. Ciò significa che aggiungere elementi agli elenchi è più veloce. Quindi, se hai intenzione di aggiungere elementi, un elenco è la strada da percorrere.

TL; DR Utilizzerei un array solo se avessi un'esigenza di ottimizzazione eccezionale o se dovessi interfacciarti con il codice C (e non puoi usare pyrex ).


1
+1 per un esempio concreto e menzione del vantaggio di velocità. La risposta migliore mi ha fatto chiedere "C'è un compromesso sulla memoria del tempo?" e "C'è qualche utilità per questo che non è un caso di memoria insufficiente molto esoterico?"
leewz,

@leewz esattamente, questo dovrebbe essere considerato come una risposta.
Gauri Shankar Badola

21

È un compromesso!

pro di ciascuno:

elenco

  • flessibile
  • può essere eterogeneo

array (es: numpy array)

  • matrice di valori uniformi
  • omogeneo
  • compatto (di dimensioni)
  • efficiente (funzionalità e velocità)
  • conveniente

2
la domanda si riferisce al modulo array in python; matrici non intorpidite. Non hanno molti professionisti tranne l'efficienza delle dimensioni. Non sono più veloci.
NONONONONO,

14

La mia comprensione è che gli array sono archiviati in modo più efficiente (ovvero come blocchi di memoria contigui rispetto a puntatori a oggetti Python), ma non sono a conoscenza di alcun vantaggio in termini di prestazioni. Inoltre, con le matrici è necessario memorizzare primitive dello stesso tipo, mentre gli elenchi possono archiviare qualsiasi cosa.


8

Gli array di librerie standard sono utili per l'I / O binario, ad esempio la traduzione di un elenco di in una stringa per scrivere, per esempio, un file wave. Detto questo, come molti hanno già notato, se hai intenzione di fare un vero lavoro, dovresti prendere in considerazione l'uso di NumPy.


6

Se utilizzerai array, prendi in considerazione i pacchetti numpy o scipy, che ti offrono array con molta più flessibilità.


5

L'array può essere utilizzato solo per tipi specifici, mentre gli elenchi possono essere utilizzati per qualsiasi oggetto.

Le matrici possono anche solo dati di un tipo, mentre un elenco può contenere voci di vari tipi di oggetti.

Le matrici sono anche più efficienti per alcuni calcoli numerici.


4
Gli array di python incorporati non sono efficienti dal punto di vista delle prestazioni, solo dal punto di vista della memoria.
martedì

Ci sono casi in cui gli array sono più efficienti in termini di elaborazione. Vedi il mio post qui sotto: stackoverflow.com/questions/176011/…
Jason Baker

0

Una differenza importante tra l'array numpy e l'elenco è che le sezioni dell'array sono viste dell'array originale. Ciò significa che i dati non vengono copiati e qualsiasi modifica alla vista verrà riflessa nell'array di origine.


0

Questa risposta riassumerà quasi tutte le domande su quando usare List e Array:

  1. La principale differenza tra questi due tipi di dati sono le operazioni che è possibile eseguire su di essi. Ad esempio, è possibile dividere un array per 3 e dividerà ogni elemento dell'array per 3. Lo stesso non si può fare con l'elenco.

  2. L'elenco fa parte della sintassi di Python, quindi non è necessario dichiararlo mentre è necessario dichiarare l'array prima di utilizzarlo.

  3. È possibile memorizzare valori di tipi di dati diversi in un elenco (eterogeneo), mentre in Array è possibile memorizzare solo valori dello stesso tipo di dati (omogeneo).

  4. Le matrici sono ricche di funzionalità e veloci, sono ampiamente utilizzate per operazioni aritmetiche e per l'archiviazione di una grande quantità di dati rispetto all'elenco.

  5. Le matrici occupano meno memoria rispetto alle liste.


0

Per quanto riguarda le prestazioni, ecco alcuni numeri che confrontano elenchi di pitone, array e array intorpiditi (tutti con Python 3.7 su un Macbook Pro 2017). Il risultato finale è che l'elenco Python è il più veloce per queste operazioni.

# Python list with append()
np.mean(timeit.repeat(setup="a = []", stmt="a.append(1.0)", number=1000, repeat=5000)) * 1000
# 0.054 +/- 0.025 msec

# Python array with append()
np.mean(timeit.repeat(setup="import array; a = array.array('f')", stmt="a.append(1.0)", number=1000, repeat=5000)) * 1000
# 0.104 +/- 0.025 msec

# Numpy array with append()
np.mean(timeit.repeat(setup="import numpy as np; a = np.array([])", stmt="np.append(a, [1.0])", number=1000, repeat=5000)) * 1000
# 5.183 +/- 0.950 msec

# Python list using +=
np.mean(timeit.repeat(setup="a = []", stmt="a += [1.0]", number=1000, repeat=5000)) * 1000
# 0.062 +/- 0.021 msec

# Python array using += 
np.mean(timeit.repeat(setup="import array; a = array.array('f')", stmt="a += array.array('f', [1.0]) ", number=1000, repeat=5000)) * 1000
# 0.289 +/- 0.043 msec

# Python list using extend()
np.mean(timeit.repeat(setup="a = []", stmt="a.extend([1.0])", number=1000, repeat=5000)) * 1000
# 0.083 +/- 0.020 msec

# Python array using extend()
np.mean(timeit.repeat(setup="import array; a = array.array('f')", stmt="a.extend([1.0]) ", number=1000, repeat=5000)) * 1000
# 0.169 +/- 0.034
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.