1

Possible Duplicate:
Variable assignment and modification (in python)

I just noticed that variable assignation in python had some behaviour which I didn't expect. For example:

import numpy as np
A = np.zeros([1, 3])
B = A

for ind in range(A.shape[1]):
    A[:, ind] = ind
    B[:, ind] = 2 * ind
print 'A = ', A
print 'B = ', B

outputs

A = [[ 0. 2. 4.]]

B = [[ 0. 2. 4.]]

While I was expecting:

A = [[ 0. 1. 2.]]

B = [[ 0. 2. 4.]]

If I replace "B = A" by "B = np.zeros([1, 3])", then I have the right thing. I can't reproduce the unexpected result in Ipython terminal. I got that result in SciTE 3.1.0 using F5 key to run the code. I'm using Python(x, y) 2.7.2.3 distro in Win7.

Community
  • 1
  • 1
user1850133
  • 2,833
  • 9
  • 29
  • 39

2 Answers2

2
B = A

makes A and B point to the same object. That's why they will be changed simultaneously.

Use

B = A.copy()

and it will work as awaited.

eumiro
  • 207,213
  • 34
  • 299
  • 261
1

In your code, B is just another name for A, so when you change one you change the other. This is a common "problem" with mutable objects in Python. With numpy arrays, you can use the copy() function.

However, this also happens with mutable containers, such as lists or dictionaries. To avoid this, you can one of one of these: (depending on the complexity of the mutable)

B = A[:]  #makes a copy of only the first level of the mutable
B = copy(A)  #same as above, returns a 'shallow copy' of A
B = deepcopy(A)  #copies every element in the mutable, on every level

Note that to use the copy and deepcopy functions, you need to import them from the standard module copy.

See also: this question

Community
  • 1
  • 1
Volatility
  • 31,232
  • 10
  • 80
  • 89
  • Alright, why can't I reproduce it in Ipython terminal? – user1850133 Jan 09 '13 at 10:40
  • As in you don't need to make a copy? I'm not entirely sure - someone tag in here? – Volatility Jan 09 '13 at 10:47
  • @user1850133: It should behave exactly the same in the IPython terminal. Perhaps if you show a transcript from the IPython session, we'll be able to see what's happening. – Mark Dickinson Jan 09 '13 at 10:48
  • @Volatility: "copy and deepcopy methods" -> "copy and deepcopy functions" – Mark Dickinson Jan 09 '13 at 10:48
  • @MarkDickinson yeah, sorry, fixed it up – Volatility Jan 09 '13 at 10:49
  • It does actually give the same result in Ipython terminal. In fact earlier I did the following, which I though was equivalent to the code in the OP. In [1]: import numpy as np [...] In [13]: A = np.zeros([1, 3]) In [14]: B = A In [15]: A Out[15]: array([[ 0., 0., 0.]]) In [16]: B Out[16]: array([[ 0., 0., 0.]]) In [17]: B = np.ones([1, 3]) In [18]: B Out[18]: array([[ 1., 1., 1.]]) In [19]: A Out[19]: array([[ 0., 0., 0.]]) – user1850133 Jan 09 '13 at 11:13
  • "is pointing to" -> "is a name for". – Karl Knechtel Jan 09 '13 at 13:08