python - 为什么 Numpy 中的 0d 数组被视为标量?
问题描述
从某种意义上说,这已经有了一个很好的答案:
人们不应该想太多。这最终对个人的心理健康和长寿有好处。
心理健康和长寿当然是好事,但是这个人的自尊心又如何受到打击,试图变得聪明并被 numpy 残酷地否认:
考虑以下我们从一些字节数据开始的地方:
a = np.linspace(0,255,6, dtype=np.uint8)
a
# array([ 0, 51, 102, 153, 204, 255], dtype=uint8)
假设我们想要添加一些东西并提升类型,所以它不会环绕。使用标量,这不起作用:
b = np.uint16(1)
a + b
# array([ 1, 52, 103, 154, 205, 0], dtype=uint8)
但是对于一个数组,它确实:
c = np.ones(1, np.uint16)
a + c
# array([ 1, 52, 103, 154, 205, 256], dtype=uint16)
所以我想让我们做一个数组。
b[...]
# array(1, dtype=uint16)
np.isscalar(b[...])
# False
可惜:
a + b[...]
# array([ 1, 52, 103, 154, 205, 0], dtype=uint8)
为什么这个 0d 数组在这里表现得像一个标量?
解决方案
https://docs.scipy.org/doc/numpy/reference/ufuncs.html#casting-rules
最后一段:
混合标量数组操作使用一组不同的转换规则,以确保标量不能“向上转换”数组,除非标量属于与大批。此规则使您可以在代码中使用标量常量(作为 Python 类型,在 ufunc 中相应地解释),而不必担心标量常量的精度是否会导致大(小精度)数组向上转换。
我认为这意味着以下表达式具有相同的效果:
In [56]: np.add(a,1)
Out[56]: array([ 1, 52, 103, 154, 205, 0], dtype=uint8)
In [57]: np.add(a,np.array(1))
Out[57]: array([ 1, 52, 103, 154, 205, 0], dtype=uint8)
为此,0d 不能“向上转换”。但是列表的行为类似于一维数组,并且会“向上转换”
In [60]: np.add(a,[1])
Out[60]: array([ 1, 52, 103, 154, 205, 256])
In [61]: np.add(a,np.array([1]))
Out[61]: array([ 1, 52, 103, 154, 205, 256])
https://docs.scipy.org/doc/numpy/reference/arrays.scalars.html
数组标量包括np.uint8(1)
等。
数组标量对象的数组优先级为 NPY_SCALAR_PRIORITY (-1,000,000.0)。
In [67]: np.uint8(1).__array_priority__
Out[67]: -1000000.0
In [68]: np.array(1,'uint8').__array_priority__
Out[68]: 0.0
数组标量具有与数组完全相同的方法。这些方法的默认行为是在内部将标量转换为等效的 0 维数组并调用相应的数组方法。
np.isscalar
做:
(isinstance(num, generic)
or type(num) in ScalarType
or isinstance(num, numbers.Number))
np.isscalar
建议使用np.ndim(x) == 0
. 这首先检查一个.ndim
属性(这将是 0d 数组的情况),如果失败,则尝试np.asarray(x).ndim
. 所以从这个意义上说,任何可以做成 0d 数组的东西都可以称为“标量”。这可能太宽泛了,因为字典很重要:npdim({})
.
推荐阅读
- reactjs - React 组件在重新渲染时滚动回顶部
- python - 我正在尝试使用 wtforms 在烧瓶中创建下拉列表,但由于某种原因我的表单无法验证,有人可以告诉我为什么吗?
- css - 基本 CSS 问题 - 如何在 CSS 样式表中进行这项工作
- tfs - 用 $ 分配 TFS 变量
- qt - 如何优化大 QStringList 的代码?
- php - 将自定义字段添加到特定类别的 woocommerce 产品
- bootstrap-4 - 如何在引导列的右中对齐图像
- kotlin - Kotlin - 无法序列化多态类。未找到序列化程序
- javascript - 待处理请求 x 秒后取消 getJSON
- android - 获取用户在设置中给出的安卓手机名称