What is the logic behind this assignment: understanding in-place assignment operations in numpy

Viewed 66

I have two fairly simple codes that give different answer. I understand it is due to the reference shared but I am not very clear what exactly happens in the 2nd case

a = np.ones(5)
b = torch.from_numpy(a)
a=np.add(a, 1, out=a)
print(a)
print(b)

[out]:

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

tensor([2., 2., 2., 2., 2.], dtype=torch.float64)

a = np.ones(5)
b = torch.from_numpy(a)
a=a+1
print(a)
print(b)

[out]:

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

tensor([1., 1., 1., 1., 1.], dtype=torch.float64)

Why isn't b changed in the second case ?

1 Answers

In the first case both a and b share the same memory (i.e. b is a view of a or in other words, b is pointing to the (array) value where a is also pointing to) and out argument guarantees that the same memory of a is updated after the np.add() operation is completed. Whereas in the second case, a is a new copy when you do a = a+1 and b is still pointing to the old value of a.

Try the second case with:

a += 1

and observe that both a and b are indeed updated.

In [7]: a = np.ones(5) 
   ...: b = torch.from_numpy(a) 
   ...: a += 1   

In [8]: a  
Out[8]: array([2., 2., 2., 2., 2.])

In [9]: b 
Out[9]: tensor([2., 2., 2., 2., 2.], dtype=torch.float64)

As @hpaulj aptly pointed out in his comment, when we do a = a+1, a new object is created and a would now point to this new (array) object instead of the old one, which is still pointed to by b. And this is the reason the (array) value of b is not updated.


To understand this behavior a bit better, you might wanna refer the excellent article by Ned Batchelder about how names are bind to values in Python

Related