Understanding a Python 3.5 List Changes the Original

I am old and have no hair to pull out. I read so many answers to similar questions that I can find on SO. I have the following code:

a = [[1,2],[3,4],[4,5]] b = ['a','b','c'] print('a:',a) print('b:',b) c = a[:] print('c == a:', c==a) print('c is a:',c is a) print('id(c) = id(a):', id(c)==id(a)) [x.extend(b) for x in c] print('c after:',c) print('a after:',a)` 

Output:

 a: [[1, 2], [3, 4], [4, 5]] b: ['a', 'b', 'c'] c == a: True c is a: False id(c) = id(a): False c after: [[1, 2, 'a', 'b', 'c'], [3, 4, 'a', 'b', 'c'], [4, 5, 'a', 'b', 'c']] a after: [[1, 2, 'a', 'b', 'c'], [3, 4, 'a', 'b', 'c'], [4, 5, 'a', 'b', 'c']] 

I am looking for the result shown as "c after:", but I don’t understand why this is changed too ?! I also tried

 c = list(a) 

and

 c = copy.copy(a) 

Of course, the simple c = a does not work as expected. What am I missing ?! Thanks.

+5
source share
4 answers

This is because you are not copying items within the list. Lists inside a not copied. Therefore, your extend method affects elements inside both lists. You should use c = copy.deepcopy(a) to copy nested elements.

+7
source

try to assign list c in this way (without .copy () solution)

 c = [] for elem in a: c.append(list(elem)) 

or one liner with list comprehension

 c = [list(elem) for elem in a] 

This provides a deep copy if you have a list inside the list and not 3 layers, of course.

The reason you failed is because you managed to copy the list properly, but the lists inside are still bound to the same memory value, so there was no copy in the item lists. This solution also copies inside the list , which is a definition of depth.

+1
source

As other posters explained, the lists inside A are not actually copied to C - they are just links to the original ones. You can see that when you run the code below:

 num_lists = [[1,2],[3,4],[4,5]] lists_copy = num_lists[:] orig_first = num_lists[0] copy_first = lists_copy[0] print('Are the first elements the same object?', orig_first is copy_first) 

What prints is "True", which means that the [1,2] inside lists_copy is actually the [1,2] of num_lists. Copying Python lists is too complicated, and I hope they change it to be more friendly in the future. At the moment, the best you can do is: lists_copy = copy.deepcopy(num_lists)

You can see how it works below:

 from copy import deepcopy lists_copy = deepcopy(num_lists) orig_first = num_lists[0] copy_first = lists_copy[0] print('Are they they the same after copying with deepcopy?', orig_first is copy_first) 

This code prints "False", which means that the list is safely copied and the balance is finally restored in the universe :)

0
source

Also keep in mind that lists are mutable types that can be changed after creation, unlike immutable types such as strings, for example. Immutable types cannot be changed after they are created. Therefore, a real copy of the line is created if you try to add a second line to it. Volatile types are subject to change. Therefore, no copy is made, and both a and c refer to the same list.

0
source

Source: https://habr.com/ru/post/1238884/


All Articles