Comment copier une liste de listes en python☘
Shallow copy (copie superficielle)☘
Les scripts suivants sont équivalents:
A = [ [1,2,3], [4,5,6], [7,8,9] ]
B = [ [], [], []]
for i in range(3):
B[i] = A[i]
A = [ [1,2,3], [4,5,6], [7,8,9] ]
B = A[:]
A = [ [1,2,3], [4,5,6], [7,8,9] ]
B = list(A)
from copy import copy
A = [ [1,2,3], [4,5,6], [7,8,9] ]
B = copy(A)
Dans chacun de ces scripts, les booléens suivants valent True
:
- B is not A
- B == A
- B[0] is A[0]
- B[1] is A[1]
- B[2] is A[2]
On notera bien que B et A ne sont pas le même objet, mais que les objets éléments de B sont les objets éléments de A. En conséquence, certaines modifications de B concernent A aussi comme on le voit ci-dessous:
>>> from copy import copy
>>> A = [[1,2,3], [4,5,6], [7,8,9]]
>>> B = copy(A)
>>> B[0][0] = 42
>>> B
[[42, 2, 3], [4, 5, 6], [7, 8, 9]]
>>> A
[[42, 2, 3], [4, 5, 6], [7, 8, 9]]
Si l'on veut que B et A soient vraiment des objets "indépendants", il nous faudra une copie profonde (paragraphe suivant).
Deep copy (copie profonde ou copie récursive)☘
Afin que l'on ait
- B is not A
- B[i] is not A[i] pour chaque i
on peut procéder ainsi:
from copy import deepcopy
A = [ [1,2,3], [4,5,6], [7,8,9] ]
B = deepcopy(A)
On parle de copie en profondeur.
On trouvera ici la documentation python sur le module copy.
Exercice☘
On dispose d'une liste de listes d'entiers de taille n×n.
Écrire une fonction de copie profonde. On n'utilisera donc pas le module copy. De simples boucles et des affectations suffisent.
Une réponse possible
Un code python à tester:
def copieProfonde(matrice):
"""
matrice -- matrice n*n
renvoie une copie profonde de matrice
"""
n = len(matrice)
return [ [matrice[i][j] for j in range(n)] for i in range(n)]
dimension = 5
A = [ [i*dimension + j for j in range(dimension)] for i in range(dimension)]
B = copieProfonde(A)
# Des tests pour vérifier:
print("B is A ?", B is A) # réponse attendue: False
print("B[0] is A[0] ?", B[0] is A[0]) # réponse attendue: False
print("B a les mêmes valeurs d'éléments que A ?", B == A) # réponse attendue: True
Remarque
Le module copy est évidemment plus complexe que cela. Il traite des cas plus généraux. Par exemple des listes de listes de listes... Notre fonction est limitée aux copies profondes de listes de listes d'objets immuables mais ne descend pas plus en profondeur et ne conviendra donc pas pour des cas comme les listes de listes de listes.