为何Python complex与np.float64相加返回Python complex而非预期的np.complex128?
嘿,你的观察真的很细致——当Python内置complex标量和np.float64标量相加时,确实会返回Python的complex类型,而非你预期的np.complex128。这不是你对数值提升规则的理解出了问题,而是Numpy和Python原生类型交互时的特殊优先级规则在起作用。
核心原因:Python原生类型的优先级高于Numpy内部提升规则
Numpy在处理Python内置标量(比如int、float、complex)和Numpy标量/数组的运算时,有一套额外逻辑:如果Numpy类型可以无损转换为对应的Python原生类型,Numpy会优先把Numpy类型转成Python类型来运算,而不是严格走自己的数值提升流程——只有当无法无损转换时,才会触发内部的提升规则。
验证这个逻辑的小测试
你可以试试把Python的complex换成Numpy的np.complex128标量,结果就完全符合你的预期了:
np.complex128(1+1j) + np.float64(1.0) # 结果类型为np.complex128
反过来,用Python的float和Numpy的np.complex128相加,同样会返回Python的complex类型:
float(1.0) + np.complex128(1+1j) # 结果是Python complex类型的(2+1j)
为什么其他组合符合你的预期?
你测试的complex(1+1j)和np.int8/16/32/64、np.float16/32的运算返回Numpy复数类型,是因为这些Numpy类型没法直接无损转成Python原生类型:
np.int8这类窄整数类型,Python的int是任意精度的,直接转换会丢失类型信息;np.float16没有对应的Python原生类型;
所以Numpy只能触发内部的数值提升规则,把Python的complex转换成对应的Numpy复数类型(np.complex128或np.complex64)来运算,结果自然就是Numpy类型了。
而np.float64刚好和Python的float完全对应(Python的float本质就是双精度浮点数),所以Numpy会优先把np.float64转成Python的float,再和Python的complex运算,最终返回Python的complex标量。
小建议
如果希望严格遵循Numpy的数值提升规则来运算,建议统一使用Numpy的标量类型(比如用np.complex128代替Python的complex),这样就能得到你预期的结果类型啦。
内容的提问来源于stack exchange,提问作者zabop

