我想对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数组:
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
答案 0 :(得分:0)
最终,这种行为归结于开发人员的自由选择,因此不必存在良好的解释。但是,我想捍卫/解释所观察到的行为,如下所述。
对于
y = np.array(1.)
y *= 1.
我们创建一个np.ndarray
对象y
,然后对其执行 操作。在这里,最自然的行为是操作(可能)更改y
的 value ,而类型应保持不变。实际上确实是这样。
此外,请注意 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
在这里,我们不创建对象,然后对它进行操作。相反,我们创建两个对象x1
和x2
,然后使用对称操作(此处为二进制乘法)将它们组合为第三个对象x
。由于x1
和x2
碰巧具有不同(但兼容)的类型,因此x
的类型并不明显:它也很可能是x1
({ {1}}或float
(x2
)的类型。令人惊讶的是,实际答案都不是,因为numpy.ndarray
的类型是x
。这种行为源于两个单独的选择。
将0维数组与标量组合会产生标量,而不是0维数组。的确,这是使您绊倒的选择。我想它也可能是反过来选择的。全局切换(例如np.float64
)将是一个不错的功能!
将NumPy数字数据类型与标准Python数字类型组合会产生NumPy数字数据类型。在这里,第一类包括诸如np.return_scalar = False
,np.int64
,{{1 }}(还有更多),而后者仅由np.float64
,np.complex128
和int
组成(对于Python 2,也是float
)。因此,complex
倍long
的结果是float
。
这两个选择确实使np.float64
成为dtype np.float64
的NumPy标量。