What exactly happens when copying and then editing this list?

I can not understand why this is happening:

A = [[1,0], [2,2]] B = list(A) print('start A:', A, 'start B:', B) A[0][0] = 999 print('end A:', A, 'end B:', B) 

This returns:

 start A: [[1, 0], [2, 2]] start B: [[1, 0], [2, 2]] end A: [[999, 0], [2, 2]] end B: [[999, 0], [2, 2]] 

Lists A and B become the same, although I explicitly copied B from A. This only happens when I do something like A [0] [0] = 999; if I replaced it with A [0] = 999, then A and B differ at the end.

What is the reason for this, and is there a way to change A in this way without affecting B?

+4
source share
5 answers

You create a shallow copy of the original list, that is, a new list containing new links to the same objects as the original list.

Changing a new list object does not change the original list. Changing objects in the new list changes the objects in the old list because they are the same.

To get a completely separate list, use copy.deepcopy() to create a deep copy.

+3
source

Both A and B contain the same two lists.

Your code is roughly equivalent to this:

 x = [1, 0] y = [2, 2] A = [x, y] B = [x, y] 

Operation A[0][0] = 999 actually just performs x[0] = 999 . That is, he does not change A himself, he changes the first element of the list x . Since both A and B have references to x , both will see a change.

+2
source

A simple copy operation, like you, is shallow, it only copies elements one level and does not recurse into nested structures. You need

 >>> import copy >>> A = [[1,0], [2,2]] >>> B = copy.deepcopy(A) >>> print('start A:', A, 'start B:', B) start A: [[1, 0], [2, 2]] start B: [[1, 0], [2, 2]] >>> A[0][0] = 999 >>> print('end A:', A, 'end B:', B) end A: [[999, 0], [2, 2]] end B: [[1, 0], [2, 2]] 
+1
source

A and B are two different names for the same piece of memory on your computer.

A and B are two separate list objects, but A[0] and B[0] are two different names for the same piece of memory on your computer. From the interpreter, do the following:

 id(B) id(A) id(B[0]) id(A[0]) 
+1
source

Python code handles object references.

Assigning a variable simply binds the name to refer to the object.

The list consists of a group of links to objects. list(A) finds all the objects referenced in A , and creates a new list with links to all the same objects. Therefore, if A is a list of lists, list(A) creates a new list with links to the same lists that were in A Therefore, a change in any of the subscriptions will be visible from both A and the new list.

copy.deepcopy exists to help you get around this when you need a full "deep" copy of something.

Once you learn to think of Python code as manipulating links to such objects, you intuitively understand when the code is likely to be accessing the same object from several places like this, although there will probably always be obscure cases, surprise you.

+1
source

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


All Articles