繁体   English   中英

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

[英]Numpy: strange different behavior of inplace and explicit operation

我想对 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 数组与浮点数相乘,为什么要更改类型? 它适用于一维数组:

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-array :

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) (D类的np.int64 ),操作y *= 1.是现在,因为这将非法需要改变dtype就地!

对于x = 1.*np.array(1.) ,让我们把它白化为

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

在这里,我们不创建一个对象,然后对其进行操作 相反,我们创建了两个对象x1x2 ,然后使用对称运算(这里是二进制乘法)将它们组合成第三个对象x 由于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 (以及更多),而后者仅包含intfloatcomplex (对于Python 2,也是long )。 因此, float时间np.float64导致np.float64

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM