numpy数组和数组标量之间的不同表现

4 投票
1 回答
73 浏览
提问于 2025-04-13 18:44

这是对这个问题的后续讨论。

当我们使用一个特定类型的numpy 数组时,进行数字运算后它会保持这个类型。
比如说,如果你给一个uint32类型的数组加1,当这个数组的值达到了uint32的最大值时,它会把值“绕回”到0,同时数组的类型依然是uint32

import numpy
a = numpy.array([4294967295], dtype='uint32')
a += 1   # will wrap to 0
print(a)
print(a.dtype)

输出结果:

uint32
[0]
uint32

但是,对于同样类型的数组 标量,这种行为就不一样了:

import numpy
a = numpy.uint32(4294967295)
print(a.dtype)
a += 1   # will NOT wrap to 0, and change the scalar type
print(a)
print(a.dtype)

输出结果:

uint32
4294967296
int64

根据数组标量的文档

使用数组标量的主要优点是它们保持数组的类型

...

因此,使用数组标量可以确保数组和标量之间的行为是相同的,无论这个值是在数组里面还是不在。

(强调是我自己的)

我的问题:
为什么我观察到数组和标量之间有不同的行为,尽管文档明确说明它们应该表现得一样?

1 个回答

3

正如评论中提到的:是的,这份文档最多也就是不够准确。我觉得它是在说同类型标量之间的行为:

import numpy
a = numpy.uint32(4294967295)
print(a.dtype)  # uint32
a += np.uint32(1)   # WILL wrap to 0 with warning
print(a)  # 0
print(a.dtype)  # uint32

不过,你的例子中的行为会因为NEP 50在NumPy 2.0中的变化而改变。所以,虽然旧的行为让人很沮丧,但也没什么办法,只能等着,除非你想提个问题,要求修改文档。具体内容可以参考迁移指南

最大的向后兼容性变化是,现在标量的精度会保持一致……np.float32(3) + 3. 现在返回的是一个float32,而之前返回的是float64

我已经确认,在你的例子中,类型保持得如预期一样。

import numpy
a = numpy.uint32(4294967295)
print(a.dtype)  # uint32
a += 1  # will wrap to 0 
print(a)  # 0
print(a.dtype)  # uint32
numpy.__version__  # '2.1.0.dev0+git20240318.6059db1'

第二个NumPy 2.0的候选版本已经发布,如果你想试试的话:https://mail.python.org/archives/list/numpy-discussion@python.org/thread/EGXPH26NYW3YSOFHKPIW2WUH5IK2DC6J/

撰写回答