正确的方法来测试numpy.dtype

Zer*_*ero 15 python numpy

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

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))
Run Code Online (Sandbox Code Playgroud)

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

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

False
Run Code Online (Sandbox Code Playgroud)

测试dtypenumpy数组的正确方法是float64什么?

aba*_*ert 21

这是lib中的一个错误.

dtype对象可以动态构造.NumPy一直这样做.在任何地方都无法保证他们被实习,所以构建一个dtype已经存在的将给你相同的.

最重要的是,np.float64实际上并不是一个dtype; 它是...我不知道这些类型被调用了什么,但是用于构造标量对象的类型是通常在a的type属性中找到的dtype,所以我将其称为a dtype.type.(注意,np.float64NumPy的数字塔类型和Python的数字塔ABCs都是子类np.dtype,当然不是.)

通常,您可以互换使用这些; 当你使用dtype.type-or,就此而言,一个原生的Python数字类型 - 其中a dtype是预期的,a dtype是动态构建的(再次,不保证被实现),但当然这并不意味着他们'相同:

>>> np.float64 == np.dtype(np.float64) == np.dtype('float64') 
True
>>> np.float64 == np.dtype(np.float64).type
True
Run Code Online (Sandbox Code Playgroud)

如果您使用内置类型,dtype.type通常是相同的:

>>> np.float64 is np.dtype(np.float64).type
True
Run Code Online (Sandbox Code Playgroud)

但是两个dtype人往往不是:

>>> np.dtype(np.float64) is np.dtype('float64')
False
Run Code Online (Sandbox Code Playgroud)

但同样,这一切都没有得到保证.(另外,请注意np.float64float使用完全相同的存储,但它们是不同的类型.当然,您也可以制作一个dtype('f8'),保证工作方式相同dtype(np.float64),但这并不意味着'f8' is,甚至==,np.float64.)

因此,通过显式传递np.float64作为其dtype参数来构造数组可能意味着在检查dtype.type属性时返回相同的实例,但这不能保证.如果你通过了np.dtype('float64'),或者你要求NumPy从数据中推断它,或者你传递一个dtype字符串来解析'f8'它等等,它就更不可能匹配.更重要的是,你绝对不会np.float64回归dtype自己.


那么,应该如何解决?

好吧,文档定义了两个dtypes 相等的意义,这是一个有用的东西,我认为这可能是你在这里寻找的有用的东西.因此,只需更换is==:

if isinstance(xx_, numpy.ndarray) and xx_.dtype == numpy.float64 and xx_.flags.contiguous:
Run Code Online (Sandbox Code Playgroud)

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


hpa*_*ulj 6

尝试:

x = np.zeros(8, dtype=np.float64)
print x.dtype is np.dtype(np.float64))    
Run Code Online (Sandbox Code Playgroud)

is测试 2 个对象的身份,它们是否具有相同的id(). 例如,它用于测试is None,但在测试整数或字符串时可能会出错。但这样的话,还有一个更进一步的问题,x.dtype而且np.float64不是同一个类。

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


x.dtype.__class__  # numpy.dtype
np.float64.__class__ # type
Run Code Online (Sandbox Code Playgroud)

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

在我的交互式测试中:

x.dtype is np.dtype(np.float64)
Run Code Online (Sandbox Code Playgroud)

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

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

两种 dtypes 都给出了12this num

x.dtype == np.float64
Run Code Online (Sandbox Code Playgroud)

测试True

另外,使用type作品:

x.dtype.type is np.float64  # True
Run Code Online (Sandbox Code Playgroud)

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

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

我不太了解ctypes它想要做什么。看起来它正在对 的data指针进行类型转换xx_xx_.ctypes._as_parameter_与 的数字相同xx_.__array_interface__['data'][0]


numpy测试代​​码中我找到了这些 dtype 测试:

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')
Run Code Online (Sandbox Code Playgroud)

numpy文档还谈到

np.issubdtype(x.dtype, np.float64)
np.issubsctype(x, np.float64)
Run Code Online (Sandbox Code Playgroud)

两者都使用issubclass.


进一步跟踪代码c表明其x.dtype == np.float64计算结果为:

x.dtype.num == np.dtype(np.float64).num
Run Code Online (Sandbox Code Playgroud)

即,将标量类型转换为 a dtype,并对.num属性进行比较。代码位于scalarapi.c, descriptor.c,multiarraymodule.cnumpy / core / src / multiarray


jcd*_*ude 6

我不确定这个 API 何时引入,但至少从 2022 年开始,您似乎可以使用numpy.issubdtype进行类型检查部分,因此可以编写:

if isinstance(arr, numpy.ndarray) and numpy.issubdtype(arr.dtype, numpy.floating):
    ...
Run Code Online (Sandbox Code Playgroud)