正确的方法来测试numpy.dtype

时间:2014-11-14 02:15:10

标签: python numpy

我正在查看具有以下if的第三方库 - 测试:

if isinstance(xx_, numpy.ndarray) and xx_.dtype is numpy.float64 and xx_.flags.contiguous:
    xx_[:] = ctypes.cast(xx_.ctypes._as_parameter_,ctypes.POINTER(ctypes.c_double))

xx_.dtype is numpy.float64似乎总是失败:

>>> xx_ = numpy.zeros(8, dtype=numpy.float64)
>>> xx_.dtype is numpy.float64

False

测试numpy数组dtypefloat64的正确方法是什么?

2 个答案:

答案 0 :(得分:20)

这是lib中的一个错误。

dtype objects可以动态构建。 NumPy一直这样做。无法保证他们被实习的任何地方,因此构建已经存在的dtype会给你相同的。{/ p>

最重要的是,np.float64实际上不是dtype;它是...我不知道这些类型被调用了什么,但是用于从数组字节构造标量对象的类型,通常在type的{​​{1}}属性中找到,所以我'我打算称它为dtype。 (注意dtype.type是NumPy的数字塔类型和Python的数字塔ABC的子类,而np.float64当然不是。)

通常情况下,您可以互换使用;当您使用np.dtype时 - 或者就此而言,使用本机Python数字类型 - 其中dtype.type是预期的,动态构建dtype(同样,不是保证被拘禁),但当然这并不意味着他们是相同的:

dtype

如果您使用内置类型,>>> np.float64 == np.dtype(np.float64) == np.dtype('float64') True >>> np.float64 == np.dtype(np.float64).type True 通常相同:

dtype.type

但是两个>>> np.float64 is np.dtype(np.float64).type True 通常不是:

dtype

但同样,这一切都无法得到保证。 (另请注意,>>> np.dtype(np.float64) is np.dtype('float64') False np.float64使用完全相同的存储空间,但它们是不同的类型。当然,您也可以制作float,保证与dtype('f8')相同{1}},但这并不意味着dtype(np.float64) 'f8',甚至is==。)

因此,通过显式传递np.float64作为其np.float64参数来构造数组可能意味着当您检查dtype属性时,您将返回相同的实例,但这不是'保证。如果您传递dtype.type,或者您要求NumPy从数据中推断出它,或者您传递一个dtype字符串以便像np.dtype('float64')等那样进行解析,那么它就更不可能匹配。更重要的是,肯定不会'f8'返回np.float64本身。


那么,应该如何解决?

嗯,文档定义了两个dtype对于相等意味着什么,这是一个有用的东西,我认为这可能是你在这里寻找的有用的东西。因此,只需将dtype替换为is

==

然而,在某种程度上,我只是猜测你正在寻找的东西。 (事实上​​它正在检查连续的标志意味着它可能会直接进入内部存储......但是为什么不检查C与Fortran顺序,或字节顺序,还是其他任何东西?)

答案 1 :(得分:1)

尝试:

x = np.zeros(8, dtype=np.float64)
print x.dtype is np.dtype(np.float64))    

is测试2个对象的身份,是否具有相同的id()。它用于测试is None,但在测试整数或字符串时可能会出错。但在这种情况下,还有一个问题,x.dtypenp.float64不是同一个类。

isinstance(x.dtype, np.dtype)  # True
isinstance(np.float64, np.dtype) # False


x.dtype.__class__  # numpy.dtype
np.float64.__class__ # type

np.float64实际上是一个函数。 np.float64()生成0.0x.dtype()会产生错误。 (更正np.float64是一个类。)

在我的互动测试中:

x.dtype is np.dtype(np.float64)

返回True。但我不知道这种情况是普遍的,还是仅仅是某种本地缓存的结果。 dtype文档提到了dtype属性:

  

dtype.num 21种不同内置类型中每种类型的唯一编号。

两个dtypes都为此12提供num

x.dtype == np.float64

测试True

此外,使用type有效:

x.dtype.type is np.float64  # True

当我导入ctypes并执行cast(使用您的xx_)时,我收到错误消息:

  

ValueError:使用序列设置数组元素。

我不太了解ctypes以了解它正在尝试做什么。看起来它正在对data的{​​{1}}指针进行类型转换,xx_xx_.ctypes._as_parameter_的数字相同。


xx_.__array_interface__['data'][0]测试代码中,我找到了这些dtype测试:

numpy

issubclass(arr.dtype.type, (nt.integer, nt.bool_) assert_(dat.dtype.type is np.float64) assert_equal(A.dtype.type, np.unicode_) assert_equal(r['col1'].dtype.kind, 'i') 文档也谈到了

numpy

两者都使用np.issubdtype(x.dtype, np.float64) np.issubsctype(x, np.float64)


进一步跟踪issubclass代码表明c被评估为:

x.dtype == np.float64

也就是说,标量类型转换为x.dtype.num == np.dtype(np.float64).num ,并比较dtype属性。代码位于.num的{​​{1}},scalarapi.cdescriptor.c