在开始使用NumPy时使用NumPy Book中的示例我注意到了一个例子:
a = zeros((4, 5))
b = ones(6)
add(b, b, a[1:3, 0:3].flat)
print(a)
返回
array([[0, 0, 0, 0, 0]
[2, 2, 2, 0, 0]
[2, 2, 2, 0, 0]
[0, 0, 0, 0, 0]])
但是,当我尝试此代码时,会导致以下错误:
添加(b,b,a [1:3,0:3] .flat)
TypeError:返回数组必须是ArrayType"
有人可以对这个问题有所了解吗?
答案 0 :(得分:3)
如果numpy.add
有2个参数,则将它们视为added
的两个操作数。如果给出3个参数,前两个是添加的参数,第三个参数是result
。实际上不是结果,而是应保存结果的数组。
因此,您在b
添加了b
,并希望将其存储在a[1:3, 0:3].flat
。
让我们试着np.add(b, b)
给出
import numpy as np
a = np.zeros((4, 5))
b = np.ones(6)
np.add(b, b)
# returns array([ 2., 2., 2., 2., 2., 2.])
所以现在我尝试a[1:3, 0:3].flat
,返回<numpy.flatiter at 0x22204e80c10>
。这意味着它返回iterator
所以它不是数组。但是我们不需要一个我们想要一个数组的迭代器。有一种名为ravel()
的方法。所以尝试a[1:3, 0:3].ravel()
会返回:
array([ 0., 0., 0., 0., 0., 0.])
所以我们有一个数组。特别是阵列也可用于存储结果(相同的形状!)。所以我试过了:
np.add(b, b, a[1:3, 0:3].ravel())
# array([ 2., 2., 2., 2., 2., 2.])
但是,让我们看看a
是否已经改变:
a
#array([[ 0., 0., 0., 0., 0.],
# [ 0., 0., 0., 0., 0.],
# [ 0., 0., 0., 0., 0.],
# [ 0., 0., 0., 0., 0.]])
所以a
没有改变。那是因为ravel()
只返回一个视图(赋值将传播到unraveled数组),否则它会返回一个副本。将结果保存在副本中是没有意义的,因为out
参数的重点在于操作是就地完成的。我只是猜测为什么要制作副本,但我认为这是因为我们从一个较大的数组中取出一部分,其中该部分在内存中不连续。
所以我建议你不要在这种情况下使用out
参数,而是使用np.add
的返回值并将其存储在a
中的指定区域内:
a[1:3, 0:3] = np.add(b, b).reshape(2,3) # You need to reshape here!
a
#array([[ 0., 0., 0., 0., 0.],
# [ 2., 2., 2., 0., 0.],
# [ 2., 2., 2., 0., 0.],
# [ 0., 0., 0., 0., 0.]])
a[1:3, 0:3].flat = np.add(b, b)
也可以。
我认为这本书已经过时了,它适用于较旧的numpy
版本,或者根本没有用过,这本书就是一个错误。