python - Numpy:就地操作和显式操作的奇怪不同行为

标签 python arrays numpy in-place numpy-ndarray

我想对 numpy 数组进行操作以使用它们的索引,并且我想包括 0 维情况。现在我遇到了一个奇怪的情况,如果我不使用就地乘法,就会出现类型转换:

In [1]: import numpy as np

In [2]: x = 1.*np.array(1.)

In [3]: y = np.array(1.)

In [4]: y *= 1.

In [5]: x
Out[5]: 1.0

In [6]: y
Out[6]: array(1.)

In [7]: type(x)
Out[7]: numpy.float64

In [8]: type(y)
Out[8]: numpy.ndarray

为什么 x 的类型与 y 不同?我知道,就地操作的实现方式不同,并且它们不会创建数组的副本,但我不明白,如果我将 0d 数组与 float 相乘,为什么类型会改变?它适用于一维数组:

In [1]: import numpy as np

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

In [3]: y = np.array([1.])

In [4]: 1.*x
Out[4]: 1.0

In [5]: 1.*y
Out[5]: array([1.])

In [7]: type(1.*x)
Out[7]: numpy.float64

In [8]: type(1.*y)
Out[8]: numpy.ndarray

我认为,这很奇怪......现在我遇到了以下问题,我必须单独处理 0d 数组:

In [1]: import numpy as np

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

In [3]: y = np.array(1.)*1.

In [4]: x[x>0]
Out[4]: array([1.])

In [5]: y[y>0]
Out[5]: array([1.])

In [6]: x[x>0] = 2.

In [7]: y[y>0] = 2.
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-7-5f9c5b138fc0> in <module>()
----> 1 y[y>0] = 2.

TypeError: 'numpy.float64' object does not support item assignment

最佳答案

最终,这种行为归结为开发人员做出的自由选择,因此不一定存在良好的解释。但是,我想对观察到的行为进行如下辩护/解释。

如果是

y = np.array(1.)
y *= 1.

我们创建一个np.ndarray对象y,然后对其进行操作。在这里,最自然的行为是操作(可能)改变 y,而类型应保持不变。这确实是实际发生的事情。

顺便说一句,请注意type和NumPy数据类型(或dtype)之间的区别。如果我们从 y = np.array(1) (np.int64 的数据类型)开始,则操作 y *= 1. 是现在非法,因为这需要就地更改dtype!

对于 x = 1.*np.array(1.) 的情况,我们将其白色化为

x1 = 1.
x2 = np.array(1.)
x = x1*x2

在这里,我们不会创建一个对象然后对其进行操作。相反,我们创建两个对象,x1x2,然后使用对称将它们组合成第三个对象,x em> 运算(此处为二进制乘法)。由于 x1x2 碰巧具有不同(但兼容)的类型,因此 x 的类型并不明显:它同样可以是x1 的类型 (float) 或 x2 的类型 (numpy.ndarray)。令人惊讶的是,实际答案都不是,因为 x 的类型是 np.float64。这种行为源于两个不同的选择。

选择1

将 0 维数组与标量组合会产生标量,而不是 0 维数组。这确实是一个让您陷入困境的选择。我想也可能是反过来选择的。全局开关(例如np.return_scalar = False)将是一个很好的功能!

选择2

将 NumPy 数值数据类型与标准 Python 数值类型相结合会产生 NumPy 数值数据类型。这里,第一类包括 np.int64np 等内容.float64np.complex128(以及更多),而后者仅由 intfloat 组成复杂(对于Python 2,也是)。因此,float 乘以 np.float64 得到 np.float64

综合起来,这两个选择确实使 x = 1.*np.array(1.) 成为 dtype np.float64 的 NumPy 标量。

关于python - Numpy:就地操作和显式操作的奇怪不同行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51930384/

相关文章:

python - 如何取消除 argmax 之外的所有条目?

python - RuntimeError : addmm(): argument 'mat1' (position 1) must be Variable, 不是 torch.FloatTensor

javascript - Jquery ajax 发布请求不起作用

python - DLL 加载失败 : The specified module could not be found

python - 在 Python 中处理矩阵

python - Numpy 将值添加(追加)到二维数组的每一行

python - Tensorflow:tf.assign 不分配任何东西

c - 操纵字符数组

php - Codeigniter - 在 HTML 表中显示来自三个表的数据作为数组对象

java - 无法完美实现QuickSort