将 int 添加到 uint8 时出现奇怪的类型转换?

Jes*_*seC 5 python numpy

我对 python/numpy 在类型转换无符号整数时的工作方式感到有些困惑。

例子:

import numpy as np
x = np.array([255], dtype=np.uint8)
y = x + 1
Run Code Online (Sandbox Code Playgroud)

这给出了结果:

In[0]: y
Out[0]: array([0], dtype=uint8)
Run Code Online (Sandbox Code Playgroud)

我知道 uint8 无法存储大于 255 的整数,因此它会循环回零。我有点期待这个。

现在我尝试:

z = x + 256
Run Code Online (Sandbox Code Playgroud)

这使:

In[1]: z
Out[1]: array([511], dtype=uint16)
Run Code Online (Sandbox Code Playgroud)

因此,在这种情况下,类型已更改为具有更多字节的类型以容纳较大的数字,但前提是要添加的整数本身不适合较小的类型。(有趣的是 x + 255 没有给出 uint16 结果)

这让我觉得有些奇怪的行为。这背后有什么逻辑吗?我本以为更一致的做法是将第一个示例中的类型更改为 uint16。

Kei*_*hWM 5

这种行为似乎源于一种可以理解的愿望:将数组转换保持在绝对最低限度。

考虑

z = np.uint8(255)
z + 1
# 256
type(z+1)
# numpy.int64
Run Code Online (Sandbox Code Playgroud)

其中文字的1类型为int. 在这种情况下,两个操作数似乎都被转换为 np.int64。但这与结果无关!

zz = np.uint8(1)
type(zz + 1)
# numpy.int64
Run Code Online (Sandbox Code Playgroud)

然而,如果我们使用数组而不是简单的整数,则转换会有所不同。

x = np.array([255], dtype=np.uint8)
x + 1
# array([0], dtype=uint8)
Run Code Online (Sandbox Code Playgroud)

在我看来,情况可能就是这样,因为将整个数组从一种类型转换为另一种类型需要大量的计算工作,因此只有在查看所有数组元素之前100% 确定有必要这样做时,才会执行此操作,即仅当另一个操作数本身不适合当前类型时。事实上,即使我们采取

b = np.int16(1)
x+b
# array([0], dtype=uint8)
Run Code Online (Sandbox Code Playgroud)

因此它实际上将右侧操作数转换为较小的类型,所有这些都是为了保存数组的类型。另一方面,当添加两个 np.array 时,类型转换始终为较大的类型。

长话短说: - 简单的整数加法总是转换为较大的操作数类型 - 如果足以表示整数,则 numpy 数组和整数的加法会转换为数组的类型,否则转换为整数的类型 -两个 numpy 数组相加会转换为较大类型的操作数(与两个整数一样)