如果 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() 仅在可能的情况下返回一个视图(赋值将传播到解开的数组),否则它返回一个副本。并且将结果保存在副本中是毫无意义的,因为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 版本一起使用,要么根本无法使用,这是书中的一个错误。