为什么0d 数组在 Numpy 不被认为是标量的?

当然,0d 数组是标量的,但是 Numpy 似乎并不这么认为... ... 我是遗漏了什么,还是只是误解了这个概念?

>>> foo = numpy.array(1.11111111111, numpy.float64)
>>> numpy.ndim(foo)
0
>>> numpy.isscalar(foo)
False
>>> foo.item()
1.11111111111
37356 次浏览

您必须以稍微不同的方式创建标量数组:

>>> x = numpy.float64(1.111)
>>> x
1.111
>>> numpy.isscalar(x)
True
>>> numpy.ndim(x)
0

看起来 麻木的标量可能有点不同的概念,从纯数学的角度来看,你可能已经习惯了。我猜你是从标量矩阵的角度来考虑的吧?

一个人不应该想太多,这最终对个人的心理健康和长寿有好处。

Numpy 标量类型的奇怪情况源于这样一个事实,即没有优雅和一致的方法将1x1矩阵降级为标量类型。即使在数学上它们是相同的事物,它们也是由非常不同的代码处理的。

如果你一直在做任何数量的科学代码,最终你会希望像 max(a)这样的东西能够处理所有大小的矩阵,甚至是标量。从数学上来说,这是一个完全合理的预期。但是对于程序员来说,这意味着在 Numpy 中呈现的标量应该具有。形状和。因此,ufuns 至少不必对 Numpy 的21种可能的标量类型的输入进行显式的类型检查。

另一方面,它们还应该使用现有的 Python 库,是的对标量类型进行显式的类型检查。这是一个进退两难的问题,因为 Numpy ndarray 在被简化为标量时必须单独更改它的类型,如果不检查所有访问,就无法知道是否发生了这种情况。实际上,按照标量类型标准使用这种方法可能会慢得离谱。

Numpy 开发人员的解决方案是从 ndarray 和 Python 标量继承自己的标量类型,这样所有标量都具有。形状。恩迪姆。T 等等。1x1矩阵将仍然存在,但是如果您知道要处理的是标量,则不鼓励使用它。虽然这在理论上应该没问题,但是偶尔你还是可以看到有些地方他们用油漆辊漏掉了,丑陋的内脏暴露出来给所有人看:

>>> from numpy import *
>>> a = array(1)
>>> b = int_(1)
>>> a.ndim
0
>>> b.ndim
0
>>> a[...]
array(1)
>>> a[()]
1
>>> b[...]
array(1)
>>> b[()]
1

没有理由 a[...]a[()]应该返回不同的东西,但它确实返回了。有一些建议可以改变这种情况,但是看起来他们忘记完成1x1数组的工作了。

一个潜在的更大的、可能无法解决的问题是 Numpy 标量是不可变的。因此,将一个标量“喷射”到一个 ndarray 中,从数学上讲,将一个数组折叠成一个标量的伴随操作,是 PITA 要实现的。你实际上不能生成一个 Numpy 标量,根据定义,它不能被转换成 ndarray,即使 newaxis神秘地在它上面工作:

>>> b[0,1,2,3] = 1
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'numpy.int32' object does not support item assignment
>>> b[newaxis]
array([1])

在 Matlab 中,增长标量的大小是完全可以接受的无脑操作。在 Numpy 中,你必须在 好好想想的任何地方都使用不和谐 a = array(a),这样你就有可能从一个标量开始,最终得到一个数组。我理解为什么 Numpy 必须这样才能很好地使用 Python,但这并不能改变许多新的切换者对此深感困惑的事实。有些人清楚地记得与这种行为作斗争并最终坚持下来,而另一些人则往往会留下一些深深的、无形的精神伤疤,这些伤疤经常出现在他们最纯真的梦中。这对所有人来说都是一个丑陋的处境。