>>> from numpy.testing import print_coercion_tables
can cast
[...]
In these tables, ValueError is '!', OverflowError is '@', TypeError is '#'
scalar + scalar
+ ? b h i l q p B H I L Q P e f d g F D G S U V O M m
? ? b h i l q l B H I L Q L e f d g F D G # # # O ! m
b b b h i l q l h i l d d d e f d g F D G # # # O ! m
h h h h i l q l h i l d d d f f d g F D G # # # O ! m
i i i i i l q l i i l d d d d d d g D D G # # # O ! m
l l l l l l q l l l l d d d d d d g D D G # # # O ! m
q q q q q q q q q q q d d d d d d g D D G # # # O ! m
p l l l l l q l l l l d d d d d d g D D G # # # O ! m
B B h h i l q l B H I L Q L e f d g F D G # # # O ! m
H H i i i l q l H H I L Q L f f d g F D G # # # O ! m
I I l l l l q l I I I L Q L d d d g D D G # # # O ! m
L L d d d d d d L L L L Q L d d d g D D G # # # O ! m
Q Q d d d d d d Q Q Q Q Q Q d d d g D D G # # # O ! m
P L d d d d d d L L L L Q L d d d g D D G # # # O ! m
e e e f d d d d e f d d d d e f d g F D G # # # O ! #
f f f f d d d d f f d d d d f f d g F D G # # # O ! #
d d d d d d d d d d d d d d d d d g D D G # # # O ! #
g g g g g g g g g g g g g g g g g g G G G # # # O ! #
F F F F D D D D F F D D D D F F D G F D G # # # O ! #
D D D D D D D D D D D D D D D D D G D D G # # # O ! #
G G G G G G G G G G G G G G G G G G G G G # # # O ! #
S # # # # # # # # # # # # # # # # # # # # # # # O ! #
U # # # # # # # # # # # # # # # # # # # # # # # O ! #
V # # # # # # # # # # # # # # # # # # # # # # # O ! #
O O O O O O O O O O O O O O O O O O O O O O O O O ! #
M ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! !
m m m m m m m m m m m m m m # # # # # # # # # # # ! m
scalar + neg scalar
[...]
array + scalar
+ ? b h i l q p B H I L Q P e f d g F D G S U V O M m
? ? b h i l q l B H I L Q L e f d g F D G # # # O ! m
b b b b b b b b b b b b b b e f d g F D G # # # O ! m
h h h h h h h h h h h h h h f f d g F D G # # # O ! m
i i i i i i i i i i i i i i d d d g D D G # # # O ! m
l l l l l l l l l l l l l l d d d g D D G # # # O ! m
q q q q q q q q q q q q q q d d d g D D G # # # O ! m
p l l l l l l l l l l l l l d d d g D D G # # # O ! m
B B B B B B B B B B B B B B e f d g F D G # # # O ! m
H H H H H H H H H H H H H H f f d g F D G # # # O ! m
I I I I I I I I I I I I I I d d d g D D G # # # O ! m
L L L L L L L L L L L L L L d d d g D D G # # # O ! m
Q Q Q Q Q Q Q Q Q Q Q Q Q Q d d d g D D G # # # O ! m
P L L L L L L L L L L L L L d d d g D D G # # # O ! m
e e e e e e e e e e e e e e e e e e F F F # # # O ! #
f f f f f f f f f f f f f f f f f f F F F # # # O ! #
d d d d d d d d d d d d d d d d d d D D D # # # O ! #
g g g g g g g g g g g g g g g g g g G G G # # # O ! #
F F F F F F F F F F F F F F F F F F F F F # # # O ! #
D D D D D D D D D D D D D D D D D D D D D # # # O ! #
G G G G G G G G G G G G G G G G G G G G G # # # O ! #
S # # # # # # # # # # # # # # # # # # # # # # # O ! #
U # # # # # # # # # # # # # # # # # # # # # # # O ! #
V # # # # # # # # # # # # # # # # # # # # # # # O ! #
O O O O O O O O O O O O O O O O O O O O O O O O O ! #
M ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! !
m m m m m m m m m m m m m m # # # # # # # # # # # ! m
[...]
1条答案
按热度按时间w46czmvw1#
正如我所提到的in another answer,numpy中的类型转换是相当复杂的,这也是你所看到的行为的根本原因。答案中链接的文档清楚地表明标量(/0 d数组)和1d数组在类型转换上是不同的,因为后者不是逐值的。
问题的前半部分你已经知道了:问题是类型转换在两种情况下发生的不同:
还有一个名为
numpy.result_type()
的帮助器,它可以告诉你相同的信息,而不必执行二进制运算:我相信,如果我们考虑一下类型转换表,就能理解示例中发生的情况:
以上是基于值的升级的当前升级表的一部分。它表示当对给定种类的两个numpy对象进行配对时,不同的类型对结果类型的贡献(具体类型见第一列第一行)。这些类型应根据单字符数据类型规范来理解。(在“单字符字符串”下面),特别是
np.dtype('f')
对应于np.float32
(f表示C样式浮点数),np.dtype('d')
(d表示C样式双精度数)对应于np.float64
(另见np.typename('f')
和'd'
)。我在上表中用黑体字标出了两项:
标量f +标量d --〉d
数组f +标量d --〉f
现在让我们看看你的例子。假设你有一个
'f'
数组a
和一个'd'
数组b
。事实上a
只有一个元素并不重要:它是长度为1的1d数组而不是0 d数组。1.当你做
a > b
的时候,你是在比较两个数组,这在上面的表格中没有说明。我的猜测是a
被广播到b
的形状,然后它的类型被转换为'd'
。我认为这是因为np.can_cast(a, np.float64)
是True
,np.can_cast(b, np.float32)
是False
。但这只是一个猜测,numpy中的许多机制对我来说并不直观。1.当你执行
a > b[0]
时,你是在比较'f'
数组和'd'
标量,所以根据上面的内容,你会得到一个'f'
数组。这就是(a + b[0]).dtype
告诉我们的。(当你使用a > b[0]
时,你看不到转换步骤,因为结果总是一个bool。)1.当你做
a[0] > b[0]
的时候,你是在比较'f'
标量和'd'
标量,所以根据上面的,你得到了一个'd'
标量,这就是(a[0] + b[0]).dtype
告诉我们的。所以我相信这与numpy中类型转换的怪癖是一致的。虽然双精度和单精度的
0.4
值看起来像是一个不幸的角落,但这个特性更深入,这个问题是一个红色的警告,警告你在混合不同的dtype时应该非常小心。最安全的做法是自己转换类型,以便控制代码中发生的事情,特别是在讨论重新考虑类型提升的某些方面时。
顺便提一句(目前),2021年5月创建的一个正在进行中的NEP 50解释了当涉及标量时类型提升是多么令人困惑,并计划最终简化一些规则。由于这也涉及到突破性的变化,它在NumPy中的实现不会在一夜之间发生。