What is the logic behind this assignment: understanding in-place assignment operations in numpy
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 ?

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
