Y a-t-il une différence de performance entre les tuples et les listes lorsqu’il s’agit de l’instanciation et l’extraction d’éléments ?
Réponses
Trop de publicités?Il y a plusieurs différences de performances entre les tuples et les listes quand il s'agit de l'instanciation et la récupération d'éléments:
-
Les Tuples contenant immuable entrées peuvent être optimisés en constantes par Python judas optimiseur. Les listes, d'autre part, get build-up à partir de zéro:
>>> from dis import dis >>> dis(compile("(10, 'abc')", '', 'eval')) 1 0 LOAD_CONST 2 ((10, 'abc')) 3 RETURN_VALUE >>> dis(compile("[10, 'abc']", '', 'eval')) 1 0 LOAD_CONST 0 (10) 3 LOAD_CONST 1 ('abc') 6 BUILD_LIST 2 9 RETURN_VALUE
-
En interne, les tuples sont stockées un peu plus efficacement que les listes, et aussi les tuples peuvent être consultées légèrement plus rapide.
Voici comment le tuple
(10, 20)
stockées:typedef struct { Py_ssize_t ob_refcnt; struct _typeobject *ob_type; Py_ssize_t ob_size; PyObject *ob_item[2]; /* store a pointer to 10 and a pointer to 20 */ } PyTupleObject;
Voici comment le liste
[10, 20]
stockées:PyObject arr[2]; /* store a pointer to 10 and a pointer to 20 */ typedef struct { Py_ssize_t ob_refcnt; struct _typeobject *ob_type; Py_ssize_t ob_size; PyObject **ob_item = arr; /* store a pointer to the two-pointer array */ Py_ssize_t allocated; } PyListObject;
Notez que le n-uplet objet intègre les deux pointeurs de données directement, tandis que les objets de la liste a une couche supplémentaire d'indirection à un groupe externe qui tiennent les deux pointeurs de données.
En général, vous pouvez vous attendre tuples d'être un peu plus rapide. Toutefois, vous devez absolument tester votre cas particulier (si la différence peut avoir un impact sur les performances de votre programme, vous vous souvenez "l'optimisation prématurée est la racine de tous les maux").
Python très facile: timeit est votre ami.
$ python -m timeit "x=(1,2,3,4,5,6,7,8)"
10000000 loops, best of 3: 0.0388 usec per loop
$ python -m timeit "x=[1,2,3,4,5,6,7,8]"
1000000 loops, best of 3: 0.363 usec per loop
et...
$ python -m timeit -s "x=(1,2,3,4,5,6,7,8)" "y=x[3]"
10000000 loops, best of 3: 0.0938 usec per loop
$ python -m timeit -s "x=[1,2,3,4,5,6,7,8]" "y=x[3]"
10000000 loops, best of 3: 0.0649 usec per loop
Donc dans ce cas, l'instanciation est presque un ordre de grandeur plus rapide pour le tuple, mais point d'accès est effectivement un peu plus rapide pour la liste! Donc, si vous êtes en train de créer un peu de tuples et l'accès à ces beaucoup de beaucoup de fois, il peut effectivement être plus rapide d'utiliser des listes à la place.
Bien sûr, si vous souhaitez modifier un élément, la liste sera certainement plus rapide puisque vous auriez besoin de créer un tout nouveau tuple de changer un élément de celui-ci (depuis les tuples sont immuables).
Les Tuples, étant immuable, sont plus efficace en terme de mémoire; les listes, pour plus d'efficacité, overallocate de la mémoire afin de permettre ajoute, sans être constamment realloc
s. Donc, si vous voulez parcourir une constante de la séquence de valeurs dans votre code (par exemple, for direction in 'up', 'right', 'down', 'left':
), les tuples sont privilégiées, car ces tuples sont pré-calculés au moment de la compilation.
L'accès et la vitesse devrait être la même (ils sont tous deux stockés comme des tableaux contigus en mémoire).
Mais, alist.append(item)
est largement préféré à l' atuple+= (item,)
lorsque vous traitez avec des données mutable. Rappelez-vous, les tuples sont destinés à être traités comme des documents sans les noms de champ.