2015-02-23 5 views
6

J'utilise python 3.4.1.
Pour une seule liste a=[1,2], si j'en fais une copie, b = a.copy() lorsque je change d'élément dans b, cela ne changera pas les éléments dans a.
Cependant, lorsque je définis une liste de listes (en fait une matrice) a = [[1,2],[3,4]], lorsque j'affecte b = a.copy(). Ce que je fais pour lister b affecte effectivement a.
J'ai vérifié leurs adresses, elles sont différentes.
Quelqu'un peut-il me dire pourquoi? Ps: Ce que j'ai fait est b[0][0] = x, et l'élément dans a été également changé.Python copier une liste de listes

+0

double possible de [Comment cloner ou copier une liste en Python? ] (http://stackoverflow.com/questions/2612802/how-to-clone-or-copy-a-list-in-python) – aruisdante

Répondre

5

De la documentation pour le module copy:

La différence entre peu profonde et la copie profonde ne concerne que les objets composés (objets qui contiennent d'autres objets, comme des listes ou des instances de classe):

  • Une copie superficielle construit un nouvel objet composé et, dans la mesure du possible, y insère des références aux objets trouvés dans l'original.
  • Une copie en profondeur construit un nouvel objet composé puis, récursivement, insère des copies des objets trouvés dans l'original.

Lorsque vous appelez régulièrement copy.copy() vous effectuez une copie peu profonde. Cela signifie que dans le cas d'une liste de listes, vous obtiendrez une nouvelle copie de la liste externe, mais elle contiendra les listes internes originales en tant qu'éléments. Au lieu de cela, vous devez utiliser copy.deepcopy(), ce qui créera une nouvelle copie des listes externe et interne.

La raison pour laquelle vous n'avez pas remarqué cela avec votre premier exemple d'utilisation copy([1,2]) est que les primitives comme int sont immuables, et il est donc impossible de changer leur valeur sans créer une nouvelle instance. Si le contenu de la liste avait été à la place des objets mutables (comme des listes, ou tout objet défini par l'utilisateur avec des membres mutables), toute mutation de ces objets aurait été vue dans les deux copies de la liste.

+0

Merci!Et encore une question sur la copie. Puis-je avoir une copie d'un cours? Comme la classe d'arbre, est-ce que je peux obtenir une copie d'un objet d'arbre t1 d'une manière simple? – jack

+0

Oui, vous pouvez utiliser le module 'copy' sur n'importe quel objet qui définit les méthodes' __copy__' et '__deepcopy__'. Voir la documentation liée dans la réponse originale pour plus de détails. Il n'y a malheureusement pas d'opération de copie 'prédéfinie' en Python comme dans les langages comme C++ (ce qui est généralement une bonne chose, car le constructeur de copie généré automatiquement par C++ est souvent incorrect pour toute classe non triviale). – aruisdante

+0

@jack Vous pouvez vérifier ce qui se passe lorsque vous utilisez la méthode de copie sur [pythontutor.com] (http://www.pythontutor.com/visualize.html#code=a+%3D+%5B%5B1,+2% 5D, +% 5B3, +4% 5D% 5D% 0Ab +% 3D + a.copie()% 0Ab% 5B0% 5D% 5B0% 5D +% 3D + 9 & mode = affichage & origine = opt-frontend.js & cumulative = faux & heapPrimitives = false & textReferences = false & py = 3 & rawInputLstJSON =% 5B% 5D & curInstr = 0). Vous pouvez voir tous les pointeurs affichés ici. –

2

Peut-être une compréhension de la liste en tant que telle:

new_list = [x[:] for x in old_list] 

... mais si vos matrices sont plus profondes d'une couche, la compréhension de la liste est probablement moins élégante que la simple utilisation deepcopy. Edit - une copie superficielle, comme indiqué, contiendra toujours des références aux objets dans la liste. Ainsi, par exemple ...

>>> this = [1, 2] 
>>> that = [33, 44] 
>>> stuff = [this, that] 
>>> other = stuff[:] 
>>> other 
[[1, 2], [33, 44]] 
>>> other[0][0] = False 
>>> stuff 
[[False, 2], [33, 44]] #the same problem as before 
>>> this 
[False, 2]    #original list also changed 
>>> other = [x[:] for x in stuff] 
>>> other 
[[False, 2], [33, 44]] 
>>> other[0][0] = True 
>>> other 
[[True, 2], [33, 44]] 
>>> stuff 
[[False, 2], [33, 44]] #copied matrix is different 
>>> this 
[False, 2]    #original was unchanged by this assignment 
+1

Il est également beaucoup moins clair pour un lecteur occasionnel que d'utiliser des méthodes de 'copy', bien qu'il soit légèrement plus performant. – aruisdante

+0

Bien sûr, il y a ça. Mais les compréhensions de liste sont les plus pythoniques, donc je suppose que cela dépend de ce qui est considéré comme «clair», et à qui. En tout cas, si la matrice est trop imbriquée alors ma suggestion ne serait pas très utile, mais pour une seule dimension je ne pense pas que ce soit trop mauvais –

-3

Il est très simple, réussissent à le faire:

b = a 

Exemple:

>>> a = [1, 2, 3] 
>>> b = a 
>>> b.append(4) 
>>> b 
[1, 2, 3, 4] 
>>> a 
[1, 2, 3, 4]