93 votes

Méthode rapide pour copier un dictionnaire en Python

J'ai un programme Python qui travaille beaucoup avec des dictionnaires. Je dois faire des copies de dictionnaires des milliers de fois. J'ai besoin d'une copie à la fois des clés et du contenu associé. La copie sera éditée et ne doit pas être liée à l'original (par exemple, les modifications apportées à la copie ne doivent pas affecter l'original).

Les clés sont des chaînes de caractères, les valeurs sont des nombres entiers (0/1).

J'utilise actuellement une méthode simple :

newDict = oldDict.copy()

Le profilage de mon code montre que l'opération de copie prend le plus de temps.

Existe-t-il des alternatives plus rapides à la dict.copy() méthode ? Quelle serait la plus rapide ?

1 votes

Si la valeur peut être soit 0 soit 1, est-ce qu'un bool est un meilleur choix qu'un int ?

5 votes

Et si vous avez besoin de milliers d'exemplaires, les bitmasks fonctionneraient-ils encore mieux ?

0 votes

@Samir n'est pas bool en Python nommé int de toute façon.

67voto

Daniel DiPaolo Points 24085

En regardant le C source pour le programme Python dict vous pouvez voir qu'ils effectuent une copie assez naïve (mais efficace). Cela se résume essentiellement à un appel à PyDict_Merge :

PyDict_Merge(PyObject *a, PyObject *b, int override)

Cela permet de vérifier rapidement s'il s'agit du même objet et s'il y a des objets à l'intérieur. Après cela, elle effectue un généreux redimensionnement/allocation unique du dict cible, puis copie les éléments un par un. Je ne vois pas comment vous pourriez aller beaucoup plus vite que la fonction intégrée copy() .

1 votes

Il semble que je doive réécrire le code pour éviter l'utilisation des dicts - ou utiliser une structure de données plus rapide qui peut faire le même travail. Merci beaucoup pour la réponse !

59voto

utdemir Points 9107

Apparemment, dict.copy est plus rapide, comme vous le dites.

[utdmr@utdmr-arch ~]$ python -m timeit -s "d={1:1, 2:2, 3:3}" "new = d.copy()"
1000000 loops, best of 3: 0.238 usec per loop
[utdmr@utdmr-arch ~]$ python -m timeit -s "d={1:1, 2:2, 3:3}" "new = dict(d)"
1000000 loops, best of 3: 0.621 usec per loop
[utdmr@utdmr-arch ~]$ python -m timeit -s "from copy import copy; d={1:1, 2:2, 3:3}" "new = copy(d)"
1000000 loops, best of 3: 1.58 usec per loop

0 votes

Merci pour la comparaison ! Je vais essayer de réécrire le code afin d'éviter l'utilisation de la copie de dict dans la plupart des endroits. Merci encore !

5 votes

La façon de faire la dernière comparaison sans compter le coût de faire l'importation à chaque fois est avec timeit 's -s argument : python -m timeit -s "from copy import copy" "new = copy({1:1, 2:2, 3:3})" . Pendant que vous y êtes, sortez également la création de la dictée (pour tous les exemples).

0 votes

Il est peut-être préférable de répéter les processus plusieurs fois, car il peut y avoir des fluctuations d'une prise de vue spécifique.

12voto

MikeVaughan Points 390

Pouvez-vous fournir un exemple de code afin que je puisse voir comment vous utilisez copy() et dans quel contexte ?

Vous pourriez utiliser

new = dict(old)

Mais je ne pense pas que ce sera plus rapide.

4voto

Alex Brasetvik Points 5314

Selon les choses que vous laissez à la spéculation, vous pouvez vouloir envelopper le dictionnaire original et faire une en quelque sorte la copie sur l'écriture.

La "copie" est alors un dictionnaire qui recherche des éléments dans le dictionnaire "parent", s'il ne contient pas déjà la clé --- mais qui introduit des modifications dans son propre dictionnaire.

Cela suppose que vous ne modifiez pas l'original et que les recherches supplémentaires ne coûtent pas plus cher.

3voto

Les mesures dépendent toutefois de la taille du dictionnaire. Pour 10000 entrées copy(d) et d.copy() sont presque les mêmes.

a = {b: b for b in range(10000)} 
In [5]: %timeit copy(a)
10000 loops, best of 3: 186 µs per loop
In [6]: %timeit deepcopy(a)
100 loops, best of 3: 14.1 ms per loop
In [7]: %timeit a.copy()
1000 loops, best of 3: 180 µs per loop

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X