Numpy`where`子句的奇怪行为

Numpy`where`子句的奇怪行为,numpy,pythonanywhere,array-broadcasting,Numpy,Pythonanywhere,Array Broadcasting,我看到ufunc where子句在Numpy 1.15.3中有一个奇怪的行为 In [1]: import numpy as np In [2]: x = np.array([[1,2],[3,4]]) In [3]: y = np.ones(x.shape) * 2 In [4]: print(x, "\n", y) [[1 2] [3 4]] [[2. 2.] [2. 2.]] In [5]: np.add(x, y, where=x==3) Out[5]: array([[2

我看到
ufunc where
子句在
Numpy 1.15.3
中有一个奇怪的行为

In [1]: import numpy as np

In [2]: x = np.array([[1,2],[3,4]])

In [3]: y = np.ones(x.shape) * 2

In [4]: print(x, "\n", y)
[[1 2]
 [3 4]]
 [[2. 2.]
 [2. 2.]]

In [5]: np.add(x, y, where=x==3)
Out[5]:
array([[2., 2.],     #<=========== where do these 2s come from???
       [5., 2.]])

In [6]: np.add(x, y, where=x==3, out=np.zeros(x.shape))
Out[6]:
array([[0., 0.],
       [5., 0.]])

In [7]: np.add(x, y, where=x==3, out=np.ones(x.shape))
Out[7]:
array([[1., 1.],
       [5., 1.]])

In [8]: np.add(x, y, where=x==3)
Out[8]:
array([[1., 1.], # <========= it seems these 1s are remembered from last computation.
       [5., 1.]])
这就产生了一个荒谬的形象:

如果我像下面那样添加
out
参数,一切正常

z = np.zeros(xx.shape)
np.sqrt(r**2 - xx**2 - yy**2, where=(r**2 - xx**2 - yy**2)>=0, out=z)

由于使用了
where
,您的输出结果中会出现垃圾数据。正如您所说,解决方法是初始化您自己的输出并将其传递给
输出

从:

如果“out”为None(默认值),则创建未初始化的返回数组。然后,在广播“where”为真的位置,用ufunc的结果填充输出数组。如果“where”是标量True(默认值),则这对应于正在填充的整个输出。请注意,未显式填充的输出将保留其未初始化的值

因此,您跳过的
out
的值(即
where
False
的索引)只保留了先前的值。这就是为什么看起来
numpy
正在“重新记录”以前计算的值,比如第一个示例代码块末尾的
1
s

正如@WarrenWeckesser在他的评论中指出的,这也意味着当
out
为空时,相同的内存块将被重新用于输出,至少在某些情况下是如此。有趣的是,您可以通过将每个输出分配给一个变量来改变得到的结果:

x = np.array([[1,2],[3,4]])
y = np.ones(x.shape) * 2

arr0 = np.add(x, y, where=x==3)
arr1 = np.add(x, y, where=x==3, out=np.zeros(x.shape))
arr2 = np.add(x, y, where=x==3, out=np.ones(x.shape))
arr3 = np.add(x, y, where=x==3)
print(arr3)
现在,您可以清楚地看到输出中的垃圾数据:

[[-2.68156159e+154 -2.68156159e+154]
 [ 5.00000000e+000  2.82470645e-309]]

“这些2从哪里来?”,见@tel的回答。2可能来自正在创建、释放的临时数组,然后将相同的内存重新用于
out
;也看到
[[-2.68156159e+154 -2.68156159e+154]
 [ 5.00000000e+000  2.82470645e-309]]