2010-07-17 4 views
9

J'apprends Python récemment, et je pratique beaucoup le langage. Une chose que j'ai trouvé intéressante est que, quand je lis à partir d'un tableau, il est presque la moitié du temps plus lent que la liste. Est-ce que quelqu'un sait pourquoi?En python, pourquoi la lecture d'un tableau est-elle plus lente que la lecture d'une liste?

voici mon code:

 
from timeit import Timer 
import array 

t = 10000 
l = range(t) 
a = array.array('i', l) 
def LIST(): 
    for i in xrange(t): 
     l[i] 

def ARRAY(): 
    for i in xrange(t): 
     a[i] 

print Timer(LIST).timeit(1000); 
print Timer(ARRAY).timeit(1000); 

la sortie est:

 
0.813191890717 
1.16269612312 

qui indique ce tableau de lecture est plus lente que la liste. Je pense que array est une mémoire de taille fixe, alors que list est une structure dynamique. J'ai donc supposé que le tableau serait plus rapide que la liste.

Est-ce que quelqu'un a une explication?

+1

possible dupe/answer: http://stackoverflow.com/questions/176011/python-list-vs-array-when-to-use - Fondamentalement array.array est un wrapper autour d'un tableau C donc je pense qu'il y a frais généraux lors de l'accès. Ne l'utilisez pas pour les maths. –

+0

Essayer de deviner l'efficacité de Python - en particulier pour ceux qui viennent d'un arrière-plan C - est souvent contre-intuitif. Code clairement d'abord, puis optimisez si vous mesurez un problème de performance; cela s'applique également à C, mais parce que les éléments du langage sont si proches de la machine, les gens oublient souvent. – msw

+1

Pour les mathématiques, vous pouvez utiliser numpy (pas encore disponible pour python 3), seul Dieu sait pourquoi numpy n'est pas une bibliothèque standard. –

Répondre

8

Il faut du temps pour envelopper un entier brut dans un Python int.

+2

Tout à fait. La fonction LIST doit juste augmenter, puis décrémenter le nombre de références pour chaque élément de la liste. D'autre part, la fonction ARRAY doit allouer de la mémoire pour chacun des entiers (sauf les plus petits qui ont une optimisation), puis la libérer à nouveau. – Duncan

1

Les listes Python ressemblent vraiment à des tableaux normaux, ce ne sont pas des listes Lisp, mais elles ont un accès aléatoire rapide.

8

list s sont « croissance dynamique des vecteurs » (très bien comme C++ est std::vector, par exemple) mais en aucun cas ralentit l'accès aléatoire pour eux (ils ne sont pas liés listes -). Les entrées des listes sont des références aux objets Python (les items): accéder à un nécessite seulement (dans CPython) un incrément du nombre de références de l'item (dans d'autres implémentations, basé sur un garbage collection plus avancé, même pas ;-). Les entrées de tableau sont des bits et des octets bruts: l'accès à celui-ci nécessite un nouvel objet Python à synthétiser basé sur cette valeur binaire. Alors .:

par exemple
$ python -mtimeit -s'import array; c=array.array("B", "bzap")' 'c[2]' 
10000000 loops, best of 3: 0.0903 usec per loop 
$ python -mtimeit -s'c=list("bzap")' 'c[2]' 
10000000 loops, best of 3: 0.0601 usec per loop 

30 temps supplémentaire pour un accès nanosecondes ne semble pas trop mal ;-). En outre, notez que timeit est BEAUCOUP plus agréable à utiliser depuis la ligne de commande - choix automatique de la répétition, unité de mesure affichée pour l'heure, etc. C'est comme ça que je l'utilise toujours (importer un module personnalisé) avec des fonctions à appeler, si nécessaire - mais ici, il n'y a pas besoin de cela) - c'est donc beaucoup plus pratique que l'importation et l'utilisation à partir d'un module!

Questions connexes