Liste Python vs tableau - quand l'utiliser?

375

Si vous créez un tableau 1d, vous pouvez l'implémenter en tant que liste, ou bien utiliser le module «tableau» dans la bibliothèque standard. J'ai toujours utilisé des listes pour les tableaux 1d.

Quelle est la raison ou les circonstances dans lesquelles je souhaiterais utiliser le module RAID à la place?

Est-ce pour l'optimisation des performances et de la mémoire ou manque-t-il quelque chose d'évident?

Corey Goldberg
la source

Réponses:

438

Fondamentalement, les listes Python sont très flexibles et peuvent contenir des données arbitraires complètement hétérogènes, et elles peuvent être ajoutées de manière très efficace, en temps constant amorti . Si vous avez besoin de réduire et d'élargir votre liste de manière efficace et sans tracas, c'est la voie à suivre. Mais ils utilisent beaucoup plus d' espace que les tableaux C .

Le array.arraytype, d'autre part, n'est qu'un mince wrapper sur les tableaux C. Il ne peut contenir que des données homogènes, toutes du même type, et il n'utilise donc que des sizeof(one object) * lengthoctets de mémoire. Généralement, vous devez l'utiliser lorsque vous devez exposer un tableau C à une extension ou à un appel système (par exemple, ioctlou fctnl).

array.arrayest également un moyen raisonnable de représenter une chaîne mutable en Python 2.x ( array('B', bytes)). Cependant, Python 2.6+ et 3.x propose une chaîne d' octets mutable comme bytearray.

Cependant, si vous voulez faire des calculs sur un tableau homogène de données numériques, il vaut mieux utiliser NumPy, qui peut automatiquement vectoriser les opérations sur des tableaux multidimensionnels complexes.

Pour faire une histoire courte : array.arrayest utile lorsque vous avez besoin d'un tableau de données C homogène pour des raisons autres que de faire des calculs .

Dan Lenski
la source
9
Numpy.ndarray a-t-il la même empreinte mémoire que array.array?
Gordon Bean
6
@Gordon, il devrait être très similaire dans le cas d'un grand tableau contigu: ils nécessiteront tous les deux sizeof(element)× (nombre d'éléments) octets, plus un petit en-tête fixe pour la surcharge. Cependant, a ndarray quelques options avancées pour le traitement des tableaux rares et discontinus, et je pense que certaines stratégies d'allocation mémoire connectables pour les grands tableaux ... certaines de ces fonctionnalités avancées rendra l' utilisateur moins la mémoire, tandis que d' autres d' améliorer les performances en utilisant plus Mémoire.
Dan Lenski
Également utile lorsque la mémoire est un problème, par exemple lors de la programmation de micro-contrôleurs avec micropython
janscas
On peut rechercher le ième élément d'un tableau en un temps constant, alors que dans la liste chaînée, il prend l'ordre «n» dans le pire des cas. Quel est le temps de recherche du ième élément dans une liste python?
Nithish Inpursuit Ofhappiness
7
@NithishInpursuitOfhappiness, une liste Python n'est pas une liste liée. Il est représenté en interne sous forme de tableau et présente les mêmes caractéristiques de complexité temporelle que ArrayList de Java. Ainsi, obtenir et définir le ième élément d'une liste Python prend un temps constant . L'ajout d'un élément à une liste Python prend un temps constant amorti car la taille du tableau est doublée lorsqu'il manque d'espace. L'insertion ou la suppression d'un élément au milieu d'une liste Python prend du temps O (n) car les éléments doivent être décalés. Pour référence, voir: wiki.python.org/moin/TimeComplexity
geofflee
66

Dans presque tous les cas, la liste normale est le bon choix. Le module de tableaux ressemble plus à un wrapper mince sur des tableaux C, qui vous donne une sorte de conteneurs fortement typés (voir la documentation ), avec accès à plus de types de type C tels que court ou double signé / non signé, qui ne font pas partie de la construction -en types. Je dirais d'utiliser le module tableaux uniquement si vous en avez vraiment besoin, dans tous les autres cas, respectez les listes.

André
la source
3
Possible, je ne l'ai jamais vraiment utilisé, mais il serait intéressant de faire quelques micro-tests.
André
13
En fait, j'ai fait un test rapide - j'ai chronométré la somme d'une liste avec 100 millions d'entrées et le même test avec le tableau correspondant, et la liste était en fait environ 10% plus rapide.
Moe
38
Les listes sont plus rapides, car les opérations sur les données "brutes" du tableau doivent créer et détruire en permanence des objets python lors de la lecture ou de l'écriture dans le tableau.
tzot
7
@Moe, comme je l'ai souligné dans ma réponse ci-dessus, la fonction intégrée de Python arrayn'est pas destinée à faire des mathématiques . Si vous essayez NumPy ndarraypour additionner un tableau de 10 ^ 8 nombres, il va complètement listdisparaître. @tzot a la bonne idée de pourquoi la fonction intégrée arrayest lente pour les mathématiques.
Dan Lenski
2
Je viens de le tester, numpy est 86,6 fois plus rapide sur ma machine.
Mark
53

Le module de tableau est une sorte de choses dont vous n'avez probablement pas besoin si vous ne savez pas pourquoi vous l'utiliseriez (et prenez note que je n'essaie pas de le dire de manière condescendante!) . La plupart du temps, le module tableau est utilisé pour s'interfacer avec le code C. Pour vous donner une réponse plus directe à votre question sur les performances:

Les tableaux sont plus efficaces que les listes pour certaines utilisations. Si vous devez allouer un tableau que vous SAVEZ ne changera pas, les tableaux peuvent être plus rapides et utiliser moins de mémoire. GvR a une anecdote d'optimisation dans laquelle le module de tableau sort vainqueur (longue lecture, mais ça vaut le coup).

D'un autre côté, une partie de la raison pour laquelle les listes consomment plus de mémoire que les tableaux est parce que python allouera quelques éléments supplémentaires lorsque tous les éléments alloués seront utilisés. Cela signifie que l'ajout d'éléments aux listes est plus rapide. Donc, si vous prévoyez d'ajouter des éléments, une liste est la voie à suivre.

TL; DR Je n'utiliserais un tableau que si vous aviez un besoin d'optimisation exceptionnel ou si vous devez vous interfacer avec du code C (et ne pouvez pas utiliser pyrex ).

Jason Baker
la source
1
+1 pour un exemple concret et mentionnant l'avantage de la vitesse. La première réponse m'a fait me demander: «Y a-t-il un compromis temps-mémoire? »et« Y a-t-il une utilité pour ce qui n'est pas un cas à faible mémoire très ésotérique? »
leewz
@leewz exactement, cela devrait être considéré comme une réponse.
Gauri Shankar Badola
21

C'est un compromis!

les avantages de chacun:

liste

  • souple
  • peut être hétérogène

tableau (ex: tableau numpy)

  • tableau de valeurs uniformes
  • homogène
  • compact (en taille)
  • efficace (fonctionnalité et vitesse)
  • pratique
Mohammad Mahdi KouchakYazdi
la source
2
la question concerne le module de tableau en python; pas des tableaux engourdis. Ils n'ont pas beaucoup d'avantages, sauf l'efficacité de la taille. Ils ne sont pas plus rapides.
NONONONONO
14

Ma compréhension est que les tableaux sont stockés plus efficacement (c'est-à-dire sous forme de blocs de mémoire contigus par rapport aux pointeurs vers des objets Python), mais je ne suis au courant d'aucun avantage en termes de performances. De plus, avec les tableaux, vous devez stocker des primitives du même type, tandis que les listes peuvent stocker n'importe quoi.

Ben Hoffstein
la source
8

Les matrices de bibliothèque standard sont utiles pour les E / S binaires, telles que la traduction d'une liste d'entiers en une chaîne pour écrire, par exemple, dans un fichier wave. Cela dit, comme beaucoup l'ont déjà noté, si vous allez faire un vrai travail, vous devriez envisager d'utiliser NumPy.

giltay
la source
6

Si vous allez utiliser des tableaux, considérez les packages numpy ou scipy, qui vous donnent des tableaux avec beaucoup plus de flexibilité.

Alex Coventry
la source
5

Un tableau ne peut être utilisé que pour des types spécifiques, tandis que les listes peuvent être utilisées pour n'importe quel objet.

Les tableaux peuvent également uniquement des données d'un type, tandis qu'une liste peut avoir des entrées de différents types d'objets.

Les tableaux sont également plus efficaces pour certains calculs numériques.

Hortitude
la source
4
Les tableaux Python intégrés ne sont pas efficaces en termes de performances, mais uniquement en termes de mémoire.
tzot
Il existe des cas où les tableaux sont plus efficaces en termes de traitement. Voir mon article ci-dessous: stackoverflow.com/questions/176011/…
Jason Baker
0

Une différence importante entre le tableau numpy et la liste est que les tranches de tableau sont des vues sur le tableau d'origine. Cela signifie que les données ne sont pas copiées et que toute modification apportée à la vue sera reflétée dans le tableau source.

vivek
la source
0

Cette réponse résumera presque toutes les requêtes sur le moment d'utiliser List et Array:

  1. La principale différence entre ces deux types de données réside dans les opérations que vous pouvez effectuer sur eux. Par exemple, vous pouvez diviser un tableau par 3 et il divisera chaque élément du tableau par 3. La même chose ne peut pas être faite avec la liste.

  2. La liste fait partie de la syntaxe de python, elle n'a donc pas besoin d'être déclarée alors que vous devez déclarer le tableau avant de l'utiliser.

  3. Vous pouvez stocker des valeurs de différents types de données dans une liste (hétérogène), tandis que dans Array, vous ne pouvez stocker que des valeurs du même type de données (homogène).

  4. Les tableaux étant riches en fonctionnalités et rapides, il est largement utilisé pour les opérations arithmétiques et pour stocker une grande quantité de données - par rapport à la liste.

  5. Les tableaux prennent moins de mémoire que les listes.

Dipen Gajjar
la source
0

En ce qui concerne les performances, voici quelques chiffres comparant les listes python, les tableaux et les tableaux numpy (tous avec Python 3.7 sur un Macbook Pro 2017). Le résultat final est que la liste python est la plus rapide pour ces opérations.

# 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
Héphaïstos
la source