今天我注意到了Numpy / Scipy数组的奇怪行为。看起来像在float中添加带整数的数组单元格可能有两种不同的结果,具体取决于分配结果的变量。下面我将介绍代码:
,而不是长篇解释import scipy as sp
array_int = sp.array([[0], [0]])
float_operand = 0.1
print array_int[0, 0] + float_operand #gives 0.1
但是
import scipy as sp
array_int = sp.array([[0], [0]])
float_operand = 0.1
array_int[0, 0] = array_int[0, 0] + float_operand
print array_int[0, 0] #gives 0
我能理解这种行为是否继承自Python,但是:
与'#34;裸露"的行为相反Python(2.7):
integer_for_sure = int(0)
integer_for_sure = integer_for_sure + 0.1
print integer_for_sure #gives 0.1 as expected
这种功能是否记录在案?有没有人以前遇到过它?
答案 0 :(得分:3)
这不是“继承自Python”的行为 - 正如您所看到的,在纯Python中向int添加float会产生float结果。相反,您可以将此行为视为“继承自C”。与Python列表不同, numpy arrays具有强大的元素类型。数组构造函数包含一个telltale可选关键字参数,其中包括:
dtype :数据类型,可选
阵列所需的数据类型。 如果没有给出,则类型将被确定为在序列中保存对象所需的最小类型。此参数只能用于“向上”数组。
重点是我的。使用np.array([[0], [0]])
创建数组时,会得到一个二维整数数组,因为整数是可以包含0
的最小数据类型。一旦创建了整数数组,它可能仅包含整数。如果您尝试插入一个浮点数,它将被转换为您注意到的整数,以便放置在数组中。
如果你想最终在数组中存储浮点数,你需要将数组初始化为一个浮点数组('upcast'它)。这可以通过使用上面提到的dtype
参数来完成,或者简单地通过将浮点值放入初始数组(例如0.0
而不是整数0
)来实现。
import scipy as sp
array_int = sp.array([[0], [0]])
array_float = sp.array([[0.0], [0]]) # Note the extra .0 to make one element a float
array_int[0, 0] = array_int[0, 0] + 0.1
print array_int[0, 0] # 0
array_float[0, 0] = array_float[0, 0] + 0.1
print array_float[0, 0] # 0.1
答案 1 :(得分:3)
与仅仅重新引用integer_for_sure
以引用float
的{{1}}对象的常规赋值相反,从而更改变量的类型,赋值给数组元素,如
integer_for_sure + 0.1
实际上是更详细的语法糖
array_int[0, 0] = array_int[0, 0] + float_operand
(这适用于旧式的类;对于新式的类看起来有点不同但是这个想法保持不变)
每种数组类型的array_int.__setitem__((0,0), array_int.__getitem__((0,0)) + float_operand)
方法对数组的类型执行其value参数的类型转换。实现赋值的实际C代码有点丑陋,涉及自定义预处理器。
另一方面
__setitem__
是
print array_int[0, 0] + float_operand
即。它从print array_int.__getitem__((0,0)) + float_operand
获取整数值,将其与array_int
相加,生成的float_operand
对象传递给float
。没有print
的中间分配,因此没有类型转换。