为什么对 0d Numpy 数组进行操作会产生 Numpy 浮点数?

Why does operating on a 0d Numpy array give a Numpy float?

提问人:argentum_109 提问时间:10/25/2023 最后编辑:XMehdi01argentum_109 更新时间:10/26/2023 访问量:108

问:

假设我有一个 0d Numpy 数组:

x = numpy.asarray(1.)

这有类型。但现在操作:numpy.ndarrayx

y = 1.*x

它现在具有类型 .使用所有 Numpy 函数时也是如此。例如,has 类型 。numpy.float64numpy.sin(x)numpy.float64

为什么?!

现在假设我有一个函数,在操作过程中,该函数必须提升数组的维度(执行一些检查或其他):

def fun(x):
    x = np.asarray(x)
    if x.ndim == 0:
        x = x[None]
    # Perform some checks and operate on x
    return x.squeeze()

为了与 Numpy 保持一致,我希望这个函数在传递给它时返回一个浮点数。但就目前而言,它返回一个 0d 数组。我可以回去,但这似乎很丑陋。这个问题有规范的解决方案吗?numpy.float641.*x.squeeze()

python numpy 浮点 numpy-ndarray

评论

4赞 pho 10/25/2023
相关新闻: stackoverflow.com/q/773030/843953
0赞 argentum_109 10/25/2023
在编写自己的函数时,有没有办法模拟这种行为,以便与 Numpy 函数保持一致?
0赞 pho 10/25/2023
我认为它应该照顾好自己,除非你专门构造一个数组来返回。你能编辑你的问题,包括你正在编写的函数的示例吗?
0赞 argentum_109 10/25/2023
是的,你是对的。我想我把两个问题混为一谈。但是,假设一旦进入函数,您必须提升(执行一些检查)的维度。您可以向下挤压以获得 0d 数组:。但是,如果将浮点数传递给函数,我想返回一个。我可以使用一面旗帜,然后这样做,但它看起来很丑。如果您不认为我在搅浑水,很高兴更新这个问题。xx = x[None]x.squeeze()numpy.float641.*x.squeeze()
1赞 pho 10/25/2023
随意更新问题,无论如何,这似乎是实际问题。

答:

1赞 hpaulj 10/25/2023 #1

一个 python 标量、一个 0d 数组和一个 numpy 标量:

In [134]: x=1.23; y = np.array(x); z = 1.*y    
In [135]: x,y,z
Out[135]: (1.23, array(1.23), 1.23)    
In [136]: type(x),type(y),type(z)
Out[136]: (float, numpy.ndarray, numpy.float64)

正如页面所指出的,这样的标量和 0d 数组之间有很多重叠。numpy scalars

它们都可以被索引

In [137]: y[()], z[()]
Out[137]: (1.23, 1.23)
    
In [139]: y[()]=2.3;y
Out[139]: array(2.3)

主要区别在于标量无法更改:

In [140]: z[()]=2.34
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Cell In[140], line 1
----> 1 z[()]=2.34

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

为什么许多操作返回标量而不是 0d 数组?我的猜测是,有一种“finalize”方法可以进行这种“清理”。关于子类化数组的文档谈到了这种终结。

有几种方法可以使这样的数组至少是 1d。

In [141]: y[None], np.atleast_1d(x), np.array(x, ndmin=1)
Out[141]: (array([2.3]), array([1.23]), array([1.23]))

np.squeeze明确指出它将返回一个 0d 数组,而不是一个 numpy 标量。我不知道有任何其他操作可以做出这样的区分。

文档可能在这方面有所启发:np.inscalar

In [143]: np.isscalar(y), np.isscalar(z)
Out[143]: (False, True)

In [144]: y.ndim, z.ndim
Out[144]: (0, 0)

isscalar是 Python 代码,具有多个测试。isinstance

评论

0赞 argentum_109 10/26/2023
谢谢。finalize 方法非常有意义,并且确实可以解释为什么对 0d 数组的操作会返回标量。挤压所有轴返回一个 0d 数组也是有道理的(感谢您向我指出文档)。在函数构造方面,我认为正确的程序是分别检查浮点数和数组。然后,任何后续操作都会返回预期的类型(如@pho指出的那样)。
0赞 argentum_109 10/26/2023
FWIW:我写了一篇简短的博文总结了这一切。