数学运算符区别 *= 或 +=
math operator difference *= or +=
我在使用运算符时发现了一件奇怪的事情,例如*=
或 +=
代码:
aa = Variable(torch.FloatTensor([[1,2],[3,4]]))
bb = aa
bb = bb*2
print(bb)
print(aa)
cc = Variable(torch.FloatTensor([[1,2],[3,4]]))
dd = cc
dd *= 2
print(cc)
print(dd)
结果如下:
Variable containing:
2 4
6 8
[torch.FloatTensor of size 2x2]
Variable containing:
1 2
3 4
[torch.FloatTensor of size 2x2]
Variable containing:
2 4
6 8
[torch.FloatTensor of size 2x2]
Variable containing:
2 4
6 8
[torch.FloatTensor of size 2x2]
如你所见,当我使用bb=bb*2
时,aa
并没有受到影响。但是,如果使用 dd *= 2
,cc
似乎指向(共享)与 cc
相同的地址,它会被更改。
他们各自的前一行是相同的,例如bb = aa
和 dd = cc
。似乎 *=
运算符将原始深拷贝更改为浅拷贝,并且更改是在复制行本身之后进行的。
我想知道这是否是一个错误。如果是,这很重要,因为它会影响基本的数学运算。通常,我认为只需使用内置的操作功能,例如torch.add()
是一个很好的解决方案。
OS: Mac OS X
PyTorch version: 3.0
How you installed PyTorch (conda, pip, source): conda
Python version: 3.6
CUDA/cuDNN version: None
GPU models and configuration: None
*-------------------------------------
我明白dd *= 2
是就地乘法,但是dd
的值怎么转成cc
?但是如果我使用 dd = dd * 2
,新值不会转移到 cc
?上一行没有区别:dd = cc
和bb =aa
。
顺便说一句,在 python(不是 pytorch 变量或张量)中,dd *= 2
和 dd = dd * 2
都不会影响 cc
值。
当您执行 dd = cc
时,dd
和 cc
现在都是对同一对象的引用(bb = aa
也是如此)。未复制任何内容!
当您执行 bb = bb * 2
时,*
运算符会创建一个新对象,并且 bb
现在会引用该对象。没有更改现有对象。
当您执行 dd *= 2
时,dd
引用的对象(以及 cc
也引用的对象)被更改。
所以不同之处在于 *
创建了一个新对象,而 =
使变量引用了一个新对象(而不是以任何方式更改对象),而 *=
更改对象。
可能 counter-intuitive x *= y
的行为与 x = x * y
不同,但这些是语言的语义,不是错误。
重复您的测试,但另外打印您的对象的 ID:
aa = Variable(torch.FloatTensor([[1,2],[3,4]]))
bb = aa
bb = bb*2
print(bb , id(bb))
print(aa , id(aa))
cc = Variable(torch.FloatTensor([[1,2],[3,4]]))
dd = cc
dd *= 2
print(cc, id(cc))
print(dd, id(dd))
这应该让您了解会发生什么。
我没有手电筒,但普通列表也有类似的做法:
aa = [1,2,3,4]
bb = aa
bb = bb*2
print(bb, id(bb))
print(aa, id(aa))
cc =[1,2,3,4]
dd = cc
dd *= 2
print(cc, id(cc))
print(dd, id(dd))
普通列表的输出(没有火花):
([1, 2, 3, 4, 1, 2, 3, 4], 140432043987888) # bb different ids
([1, 2, 3, 4], 140432043930400) # aa different ids
([1, 2, 3, 4, 1, 2, 3, 4], 140432043916032) # cc same id, same object
([1, 2, 3, 4, 1, 2, 3, 4], 140432043916032) # dd same id, same object
我在使用运算符时发现了一件奇怪的事情,例如*=
或 +=
代码:
aa = Variable(torch.FloatTensor([[1,2],[3,4]]))
bb = aa
bb = bb*2
print(bb)
print(aa)
cc = Variable(torch.FloatTensor([[1,2],[3,4]]))
dd = cc
dd *= 2
print(cc)
print(dd)
结果如下:
Variable containing:
2 4
6 8
[torch.FloatTensor of size 2x2]
Variable containing:
1 2
3 4
[torch.FloatTensor of size 2x2]
Variable containing:
2 4
6 8
[torch.FloatTensor of size 2x2]
Variable containing:
2 4
6 8
[torch.FloatTensor of size 2x2]
如你所见,当我使用bb=bb*2
时,aa
并没有受到影响。但是,如果使用 dd *= 2
,cc
似乎指向(共享)与 cc
相同的地址,它会被更改。
他们各自的前一行是相同的,例如bb = aa
和 dd = cc
。似乎 *=
运算符将原始深拷贝更改为浅拷贝,并且更改是在复制行本身之后进行的。
我想知道这是否是一个错误。如果是,这很重要,因为它会影响基本的数学运算。通常,我认为只需使用内置的操作功能,例如torch.add()
是一个很好的解决方案。
OS: Mac OS X
PyTorch version: 3.0
How you installed PyTorch (conda, pip, source): conda
Python version: 3.6
CUDA/cuDNN version: None
GPU models and configuration: None
*-------------------------------------
我明白dd *= 2
是就地乘法,但是dd
的值怎么转成cc
?但是如果我使用 dd = dd * 2
,新值不会转移到 cc
?上一行没有区别:dd = cc
和bb =aa
。
顺便说一句,在 python(不是 pytorch 变量或张量)中,dd *= 2
和 dd = dd * 2
都不会影响 cc
值。
当您执行 dd = cc
时,dd
和 cc
现在都是对同一对象的引用(bb = aa
也是如此)。未复制任何内容!
当您执行 bb = bb * 2
时,*
运算符会创建一个新对象,并且 bb
现在会引用该对象。没有更改现有对象。
当您执行 dd *= 2
时,dd
引用的对象(以及 cc
也引用的对象)被更改。
所以不同之处在于 *
创建了一个新对象,而 =
使变量引用了一个新对象(而不是以任何方式更改对象),而 *=
更改对象。
可能 counter-intuitive x *= y
的行为与 x = x * y
不同,但这些是语言的语义,不是错误。
重复您的测试,但另外打印您的对象的 ID:
aa = Variable(torch.FloatTensor([[1,2],[3,4]]))
bb = aa
bb = bb*2
print(bb , id(bb))
print(aa , id(aa))
cc = Variable(torch.FloatTensor([[1,2],[3,4]]))
dd = cc
dd *= 2
print(cc, id(cc))
print(dd, id(dd))
这应该让您了解会发生什么。
我没有手电筒,但普通列表也有类似的做法:
aa = [1,2,3,4]
bb = aa
bb = bb*2
print(bb, id(bb))
print(aa, id(aa))
cc =[1,2,3,4]
dd = cc
dd *= 2
print(cc, id(cc))
print(dd, id(dd))
普通列表的输出(没有火花):
([1, 2, 3, 4, 1, 2, 3, 4], 140432043987888) # bb different ids
([1, 2, 3, 4], 140432043930400) # aa different ids
([1, 2, 3, 4, 1, 2, 3, 4], 140432043916032) # cc same id, same object
([1, 2, 3, 4, 1, 2, 3, 4], 140432043916032) # dd same id, same object