Adresse : http://docs.python.org/3.3/library/copy.html
Le module copy permet d’effectuer des copies “superficielles” ou “en profondeur” d’objets mutables, notamment de listes.
Pour cela, il met à notre disposition les fonctions copy et deepcopy.
Les “copies en profondeur” sont utiles pour les listes de listes (les matrices, par exemple), pour créer une copie y totalement indépendante d’un objet original x (non seulement différence des adresses de x et y, mais différence des adresses des éléments qui se correspondent dans x et y). Les exemples ci-dessous illustrent ces subtilités :
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
>>> from copy import * # importe les fonctions copy et deepcopy >>> a = list(range(0,5)); a # place dans a la liste [0,1,2,3,4] [0, 1, 2, 3, 4] >>> id(a) # voici où est située cette liste en mémoire 4318102808 >>> x = [2013, a, a, a]; x # dans x, une liste avec 2013 puis trois exemplaires de a [2013, [0, 1, 2, 3, 4], [0, 1, 2, 3, 4], [0, 1, 2, 3, 4]] >>> y = x; y # poser y = x, c'est faire pointer y sur la même liste que x [2013, [0, 1, 2, 3, 4], [0, 1, 2, 3, 4], [0, 1, 2, 3, 4]] >>> z = copy(x); z # effectue une copie ''superficielle'' (shallow copy ) [2013, [0, 1, 2, 3, 4], [0, 1, 2, 3, 4], [0, 1, 2, 3, 4]] >>> id(x), id(y), id(z) # x et y pointent sur la même adresse, mais pas z (4318102448, 4318102448, 4318102592) >>> [id(e) for e in x] # les adresses des éléments de x (et aussi de y, forcément) [4322826768, 4318102808, 4318102808, 4318102808] >>> [id(e) for e in z] # les adresses internes à z sont les mêmes que pour x !!! [4322826768, 4318102808, 4318102808, 4318102808] >>> x[0] = 9999 # modifier x[0] crée un nouvel objet donc une nouvelle adresse >>> y # voici le nouveau contenu de x et de y [9999, [0, 1, 2, 3, 4], [0, 1, 2, 3, 4], [0, 1, 2, 3, 4]] >>> (id(x),id(y)) # c'est normal car les adresses de x, y sont restées les mêmes (4318102448, 4318102448) >>> z # en revanche, la liste pointée par z n'a pas changé [2013, [0, 1, 2, 3, 4], [0, 1, 2, 3, 4], [0, 1, 2, 3, 4]] >>> id(z) # normal car l'adresse de z, inchangée, diffère de celle de x 4318102592 >>> a[4] = -1000 # modifions maintenant seulement a[4] >>> id(a) # l'adresse de la liste a n'a pas changé 4318102808 >>> y # donc la modification de a se voit dans x, et dans y [9999, [0, 1, 2, 3, -1000], [0, 1, 2, 3, -1000], [0, 1, 2, 3, -1000]] >>> z # mais aussi dans z !!! [2013, [0, 1, 2, 3, -1000], [0, 1, 2, 3, -1000], [0, 1, 2, 3, -1000]] >>> zzz = deepcopy(x) # on fait maintenant une copie ''profonde'' de x >>> [id(e) for e in x] # rappelons les adresses des composantes de x [4322826800, 4318102808, 4318102808, 4318102808] >>> [id(e) for e in zzz] # les composantes mutables de zzz ont changé d'adresse [4322826800, 4318102880, 4318102880, 4318102880] >>> a[4]=777 # on modifie à nouveau un élément de a >>> x # les composantes de x, pointant sur a, sont modifiées, normal [9999, [0, 1, 2, 3, 777], [0, 1, 2, 3, 777], [0, 1, 2, 3, 777]] >>> zzz # mais celles de zzz n'ont pas changé (normal aussi) [9999, [0, 1, 2, 3, -1000], [0, 1, 2, 3, -1000], [0, 1, 2, 3, -1000]] |
Important : l’instruction y = x[:] équivaut à une copie superficielle (c’est-à-dire à y = copy.copy(x)), ce qui permet de se passer du module copy (à condition qu’on veuille copier des listes dont les composantes sont non mutables ! ! !)
Retour à l’accueil du cours Python/Numpy
Sommaire du chapitre 7
- Le module random
- Le module decimal
- Le module fractions
- Le module string
- Le module itertools
- Les modules operator et functools
- Le module time
- La classe Counter du module collections
- La classe deque du module collections
- Le module heapq
- Le module bisect
- Le module copy
- Autres modules et adresses utiles