我试图减少代码中的复制量,但在处理 numpy 数组切片和 View 时遇到了令人惊讶的行为,如中所述:
Scipy wiki page on copying numpy arrays
我偶然发现了以下行为,这对我来说是出乎意料的:
案例 1.:
import numpy as np
a = np.ones((3,3))
b = a[:,1:2]
b += 5
print a
print b.base is a
如预期的那样,输出:
array([[ 1., 6., 1.],
[ 1., 6., 1.],
[ 1., 6., 1.]])
True
情况 2:在一行中执行切片和添加时,情况看起来有所不同:
import numpy as np
a = np.ones((3,3))
b = a[:,1:2] + 5
print a
print b.base is a
令我惊讶的部分是 a[:,1:2] 似乎没有创建 View ,然后将其用作左侧参数,因此,输出:
array([[ 1., 1., 1.],
[ 1., 1., 1.],
[ 1., 1., 1.]])
False
也许有人可以阐明为什么这两种情况不同,我想我遗漏了什么。
解决方案:我忽略了一个明显的事实,即“+”运算符,而不是就地运算符“+=”,它总是会创建一个副本,所以它实际上不相关,而是切片其他比如何为 numpy 数组定义就地运算符。
为了说明这一点,以下生成与案例 2 相同的输出:
import numpy as np
a = np.ones((3,3))
b = a[:,1:2]
b = b + 5
print a
print b.base is a
最佳答案
以上内容与:
>>> a=np.arange(5)
>>> b=a
>>> b
array([0, 1, 2, 3, 4])
>>> b+=5
>>> a
array([5, 6, 7, 8, 9])
>>> b
array([5, 6, 7, 8, 9])
>>> b=b+5
>>> b
array([10, 11, 12, 13, 14])
>>> a
array([5, 6, 7, 8, 9])
至少在我看来,这完全是意料之中的行为。 b+=x
运算符调用 __iadd__
重要的是首先尝试修改数组,因此它将更新 b
这仍然是 a
的一个 View 。 b=b+x
运算符调用 __add__
创建新的临时数据,然后将其分配给 b
。
对于 a[i] +=b
序列是(在 numpy 中):
a.__setitem__(i, a.__getitem__(i).__iadd__(b))
关于python - numpy 数组切片的意外结果(查看与复制),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18155972/