3

Here is minimal code:

A = np.zeros((2,2))
B = A
A[0,0] = 2
print A
print B

which outputs:

[[ 2.  0.]
 [ 0.  0.]]
[[ 2.  0.]
 [ 0.  0.]]

I expected B to stay them same, but instead it's updated to the new value of A? What are the mechanics behind this and what's the general rule to know why/when this would happen? It seems kind of dangerous...

space_voyager
  • 1,984
  • 3
  • 20
  • 31
  • Possible duplicate of [How do I pass a variable by reference?](https://stackoverflow.com/questions/986006/how-do-i-pass-a-variable-by-reference) – Thierry Lathuille Feb 19 '18 at 18:27
  • 5
    This is the way Python assignment **always** works. `A = B` merely means "the object referred to by the name A is now referred to by the name B as well". Again, this is easy to remember, it **always** works this way. See https://nedbatchelder.com/text/names.html – juanpa.arrivillaga Feb 19 '18 at 18:28
  • 2
    `A` and `B` refer to the same backing data. Actually, in this case it's even stronger: they refer to the same *object!* – Mateen Ulhaq Feb 19 '18 at 18:28
  • @ThierryLathuille to elaborate a little, that duplicate is a question more about evaluation strategy. In this question, the issue is how assignment works. However, in Python, parameter passing is semantically equivalent to assignment! – juanpa.arrivillaga Feb 19 '18 at 18:33
  • With numpy arrays there's an added layer of 'view' versus 'copy': https://stackoverflow.com/questions/48871320/why-does-using-on-numpy-arrays-modify-the-original-array. – hpaulj Feb 19 '18 at 19:30

1 Answers1

3

This is in general python behaviour and not specific to numpy. If you have an object such as list you will see a similar behaviour.

a = [1]
b = a
b[0] = 7
print a
print b

will output

[7]
[7]

This happens because variable a is pointing to a memory location where the array [1] is sitting and then you make b point to the same location. So if the value at that location changes, both the variables are still pointing there. If you want to get around this behaviour you'll need to use the .copy() function like this.

A = np.zeros((2,2))
B = A.copy()
A[0,0] = 2
print A
print B

which outputs..

[[2. 0.]
[0. 0.]]
[[0. 0.]
[0. 0.]]

Using the copy() function will spawn a whole new object instead of pointing to the old one. Caution: This may not be the ideal way to do it since copying a huge numpy array can be computationally expensive

EDIT: Removed the word mutable since the behaviour is also applicable to immutables.

juanpa.arrivillaga
  • 88,713
  • 10
  • 131
  • 172
Backalla
  • 86
  • 8