second appending of numpy array to list change the first entry in the list as well

Issue

In the following code:

E=np.zeros((2,2))
H=np.zeros((2,2))+1
L=[]
L.append(E)
E=H
L.append(E)
print(L)

the output is what I expect to be:

[array([[0., 0.],
    [0., 0.]]), array([[1., 1.],
    [1., 1.]])]

that is L[0] remains the same after the second appending.
However, for the code:

E=np.zeros((2,2))
H=np.zeros((2,2))+1
L=[]
L.append(E)
E[0,0]=H[0,0]
L.append(E)
print(L)

the output is

[array([[1., 0.],
        [0., 0.]]), array([[1., 0.],
        [0., 0.]])]

that is L[0] was changed after the second appending. can someone explain why there is difference?
I know that appending E.copy() is more safe but I do not understand what is the source for the difference since E[0,0] is numpy and not list.

Solution

In your first example the variable E gets assigned to the same array as H refers to (the second array). The original relation of E to the first array is simply overwritten. That’s why the first list element is unaffected in the first example.
In your second example, you change the content of the array to which E refers to and to which the first entry of that list has also be assigned to. Therefore it changes.

The action of = in python is rather explicit. Just assign some reference to a variable. Whatever that variable referred to before, simply does not matter.

You already had the answer by suggesting to use copy for appending to the list. If you want to keep track of the used matrices, you have to store a copy of each anyway. Otherwise they would get lost. So:

E = np.zeros((2,2))
L = [E.copy()]
E[0,0] = 1
L.append(E.copy())

will give you

[array([[0., 0.],
        [0., 0.]]),
 array([[1., 0.],
        [0., 0.]])]

Answered By – Thomas Hilger

This Answer collected from stackoverflow, is licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply

(*) Required, Your email will not be published