9

I found a bug in my large code, and I simplified the issue to the case below.

Although in each step I only change w2, but when at each step I print out w1, it is also changed, because end of the first loop I assign them to be equal. I read for this but there was written in case I make w1 = w2[:] it will solve the issue but it does not

import numpy as np
import math

w1=np.array([[1,2,3],[4,5,6],[7,8,9]])
w2=np.zeros_like(w1)
print 'w1=',w1
for n in range(0,3):
    for i in range(0,3):
        for j in range(0,3):
            print 'n=',n,'i=',i,'j=',j,'w1=',w1
            w2[i,j]=w1[i,j]*2

    w1=w2[:]


#Simple tests
# w=w2[:]
# w1=w[:]

# p=[1,2,3]
# q=p[:];
# q[1]=0;
# print p
ivan_pozdeev
  • 33,874
  • 19
  • 107
  • 152
Soyol
  • 763
  • 2
  • 10
  • 29
  • You're assigning a copy of `w2` to `w1` each time, only after modifying `w1`, correct? But you don't expect `w1` to remain `[[1,2,3],[4,5,6],[7,8,9]]`, do you? – Brian Cain Mar 14 '16 at 01:42
  • 1
    Why not just do `w2 = w1 * 2`? – Suever Mar 14 '16 at 01:43
  • 1
    Ugh, yes, thanks @Suever -- let's take a step back: what are you trying to do? – Brian Cain Mar 14 '16 at 01:44
  • I start with initial values for w1, then in loops at each step of n I assign values to w2, and when I did for its all elements then I feed it in to w1, and make w1 equal to that. but when for the first time I do this(i.e. w1=w2), whenever I change w2 during loop w1 changes as well immediately. – Soyol Mar 14 '16 at 01:45
  • @BrianCain the reason for that is just I want to make an example of my code, there it is more complicated. okay. take w2[i,j]=w1[i,j]+(2*i+j) instead – Soyol Mar 14 '16 at 01:48
  • @Soheilsmz yes because you need to assign the *values* of `w2` into `w1`. As it is, you are simply pointing `w1` and `w2` to the same underlying object. – Suever Mar 14 '16 at 01:48
  • @Suever I know it is because of that. but dont know how to avoid that! any solutions – Soyol Mar 14 '16 at 01:49
  • @Soheilsmz just posted two options that should work. – Suever Mar 14 '16 at 01:56
  • Does this answer your question? [List changes unexpectedly after assignment. Why is this and how can I prevent it?](https://stackoverflow.com/questions/2612802/list-changes-unexpectedly-after-assignment-why-is-this-and-how-can-i-prevent-it) – Thomas Weller Mar 04 '22 at 12:01

1 Answers1

15

The issue is that when you're assigning values back to w1 from w2 you aren't actually passing the values from w1 to w2, but rather you are actually pointing the two variables at the same object.

The issue you are having

w1 = np.array([1,2,3])
w2 = w1

w2[0] = 3

print(w2)   # [3 2 3]
print(w1)   # [3 2 3]

np.may_share_memory(w2, w1)  # True

The Solution

Instead you will want to copy over the values. There are two common ways of doing this with numpy arrays.

w1 = numpy.copy(w2)
w1[:] = w2[:]

Demonstration

w1 = np.array([1,2,3])
w2 = np.zeros_like(w1)

w2[:] = w1[:]

w2[0] = 3

print(w2)   # [3 2 3]
print(w1)   # [1 2 3]

np.may_share_memory(w2, w1)   # False
Suever
  • 64,497
  • 14
  • 82
  • 101
  • Thank you, that is my mistake – Soyol Mar 14 '16 at 01:57
  • 1
    Do you assert that `w1=w2[:]` makes them point to the same object? It's not like this with `list`s. – ivan_pozdeev Mar 14 '16 at 02:17
  • 1
    @ivan_pozdeev Yes this is correct. Typically a numpy array created simply using an indexing operation (such as `w2[:]`) is simply a different "view" of the same underlying data in memory. This can be verified using [`numpy.may_share_memory(w1, w2)`](http://docs.scipy.org/doc/numpy-dev/reference/generated/numpy.may_share_memory.html) – Suever Mar 14 '16 at 02:26
  • 2
    @ivan_pozdeev [here is a great answer](http://stackoverflow.com/a/18808601/670206) that goes over some of the finer points of memory management in numpy – Suever Mar 14 '16 at 02:29