我有两个相当简单的代码,给出了不同的答案。我知道这是由于共享的参考,但我不太清楚在第二种情况下究竟发生了什么
a = np.ones(5)
b = torch.from_numpy(a)
a=np.add(a, 1, out=a)
print(a)
print(b)
[输出]:
[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)
[输出]:
[2. 2.2. 2.2.]
Tensor([1., 1., 1., 1., 1.], dtype=torch.float64(
为什么在第二种情况下没有改变b?
在第一种情况下,a
和b
共享相同的内存(即b
是a
的视图,换句话说,b
指向(数组(值,a
也指向该值(,并且out
参数保证在np.add()
操作完成后更新a
的相同内存。 而在第二种情况下,当您执行a = a+1
并且b
仍然指向a
的旧值时,a
是新副本。
尝试第二种情况:
a += 1
并观察a
和b
确实都已更新。
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)
正如@hpaulj在他的评论中恰当地指出的那样,当我们做a = a+1
时,会创建一个新对象,a
现在将指向这个新的(数组(对象而不是旧的对象,该对象仍然由b
指向。这就是b
的(数组(值未更新的原因。
为了更好地理解这种行为,你可能想参考 Ned Batchelder 关于名称如何绑定到 Python 中的值的优秀文章
。