如何在python中识别numpy类型?


100

如何可靠地确定一个对象是否具有numpy类型?

我意识到这个问题与鸭子类型的哲学背道而驰,但是我们的想法是确保一个函数(使用scipy和numpy)永远不会返回一个numpy类型,除非使用numpy类型进行调用。 这是另一个问题的解决方案,但是我认为确定对象是否具有numpy类型的一般问题与原始问题相距甚远,因此应将它们分开。


一个问题:如果您(或者说scipy)定义了一个继承numpy类型的类型,那该算不算?(我相信您不能在Python中子类化numpy类型,但是可以在C模块中子类化,而且我认为您也可以在PyPy中子类化numpypy类型……因此,这可能没关系,但这并不是可以想象的。)
abarnert 2012年

我没想到 基本上,您的评论指出问题比预期的要难。老实说,这种高水平的考虑对我的情况而言是过大的手段。对于一般的可移植答案,我想说的是,只要定义了行为,就可以了。
道格拉斯·B·斯台

Answers:


115

使用内置type函数获取类型,然后可以使用该__module__属性找出定义的位置:

>>> import numpy as np
a = np.array([1, 2, 3])
>>> type(a)
<type 'numpy.ndarray'>
>>> type(a).__module__
'numpy'
>>> type(a).__module__ == np.__name__
True

是例如numpy.ma.MaskedArray不是足够的numpy类型?
panda-

如果您想要numpy。*中的任何内容,则只需遍历模块的父包。(到那时,您显然希望将其包装在一个函数中。)并且如果要将pandas DataFrames计数为numpyish,请添加一个或进行测试。等等。关键是,当您想做一些与松散的手动类型切换不同寻常的操作时,您必须知道真正的要求,但是一旦知道,它就很容易实现。
abarnert'3

1
这种解决方案似乎非常不可思议,它依赖于隐藏的属性。但是,也许这只是一个品味问题?
j08lue

2
@ j08lue它们不是隐藏的属性,而是有文献记载的特殊属性。尽管如此,它还是不可思议的,但是我认为这是问题的内在原因。(我认为,Python的强项是,当您想做某种语言不鼓励的事情时,最好的解决方案通常看起来丑陋得足以使您断言您正在做的事情通常是个坏主意。)
abarnert

69

我想出的解决方案是:

isinstance(y, (np.ndarray, np.generic) )

但是,并不是所有的numpy类型都保证是np.ndarray或都100%清晰np.generic这可能不是版本可靠的。


1
我想您可以过滤dir(numpy)类型和内置函数(以及类,但是我认为它没有任何东西),并使用它来生成一个元组来isinstance抵抗它,这将是可靠的。(我相信您可以将内置函数传递给isinstance,无论它们是否实际上是类型构造函数,但您都必须进行检查。)
abarnert 2012年

是的,它们都应该是这两个AFAIK的子类。
seberg 2012年

@seberg谢谢。目前看来确实如此,但是python文档对此并不十分清楚,并且可以想象将来会发生变化。
Douglas B. Staple 2012年

19

老问题,但我想出一个明确的答案,举一个例子。我也遇到了同样的问题,也没有找到明确的答案,因此可以使问题保持​​新鲜感。关键是确保已numpy导入,然后运行isinstance布尔。虽然这看起来很简单,但是如果您要对不同的数据类型进行一些计算,则在开始一些numpy向量化操作之前,此小检查可以作为一项快速测试。

##################
# important part!
##################

import numpy as np

####################
# toy array for demo
####################

arr = np.asarray(range(1,100,2))

########################
# The instance check
######################## 

isinstance(arr,np.ndarray)

9

这实际上取决于您要查找的内容。

  • 如果要测试序列是否实际上是a ndarray,则a isinstance(..., np.ndarray)可能是最简单的。确保您不要在后台重新加载numpy,因为模块可能有所不同,但否则应该没问题。MaskedArraysmatrixrecarray是所有子类ndarray,所以你应该设置。
  • 如果要测试标量是否为numpy标量,事情会变得更加复杂。您可以检查它是否具有shapedtype属性。您可以将其dtype与基本dtype 进行比较,可以在中找到其基本列表np.core.numerictypes.genericTypeRank。请注意,此列表的元素是字符串,因此您必须执行tested.dtype is np.dtype(an_element_of_the_list)...

+1。如果您实际上正在寻找“是一种numpy类型” 之外的东西,并且可以定义那是什么,那比其他答案要好。在大多数情况下,您应该寻找可以定义的特定内容。
abarnert 2012年

8

要获取类型,请使用内置type函数。使用in运算符,可以检查类型是否为numpy类型,方法是检查其是否包含字符串numpy;

In [1]: import numpy as np

In [2]: a = np.array([1, 2, 3])

In [3]: type(a)
Out[3]: <type 'numpy.ndarray'>

In [4]: 'numpy' in str(type(a))
Out[4]: True

(顺便说一下,此示例在IPython中运行。非常便于交互使用和快速测试。)


2
这行得通,但是如果您定义一个名为“ numpygroup”的类型,则会得到误报。另外,如果可以避免的话,取决于类型的字符串表示是一个坏主意,在这种情况下,可以这样做。请查看其模块。
abarnert 2012年

使用模块确实是更好的解决方案。
罗兰·史密斯

可以使用正则表达式
omkaartg,

@ Omkaar.K正则表达式可以用于什么?以稍微复杂一点的方式进行完全相同的检查?
abarnert

我说的是@abamert“可能”,对于这样的简单任务,正则表达式看起来也很复杂,但是对于大型字符串处理任务来说,它非常有用,因此学习它不是一个坏主意。我想您已经知道,既然您的投资组合将您描述为高级程序员?
omkaartg's

3

请注意,它本身type(numpy.ndarray)就是一个type,请注意布尔和标量类型。如果不是直观或简单的方法,不要太气disc,起初是很痛苦的。

另请参阅:-https : //docs.scipy.org/doc/numpy-1.15.1/reference/arrays.dtypes.html-https : //github.com/machinalis/mypy-data/tree/master/numpy- py

>>> import numpy as np
>>> np.ndarray
<class 'numpy.ndarray'>
>>> type(np.ndarray)
<class 'type'>
>>> a = np.linspace(1,25)
>>> type(a)
<class 'numpy.ndarray'>
>>> type(a) == type(np.ndarray)
False
>>> type(a) == np.ndarray
True
>>> isinstance(a, np.ndarray)
True

布尔值的乐趣:

>>> b = a.astype('int32') == 11
>>> b[0]
False
>>> isinstance(b[0], bool)
False
>>> isinstance(b[0], np.bool)
False
>>> isinstance(b[0], np.bool_)
True
>>> isinstance(b[0], np.bool8)
True
>>> b[0].dtype == np.bool
True
>>> b[0].dtype == bool  # python equivalent
True

标量类型的更多乐趣,请参见:-https : //docs.scipy.org/doc/numpy-1.15.1/reference/arrays.scalars.html#arrays-scalars-built-in

>>> x = np.array([1,], dtype=np.uint64)
>>> x[0].dtype
dtype('uint64')
>>> isinstance(x[0], np.uint64)
True
>>> isinstance(x[0], np.integer)
True  # generic integer
>>> isinstance(x[0], int)
False  # but not a python int in this case

# Try matching the `kind` strings, e.g.
>>> np.dtype('bool').kind                                                                                           
'b'
>>> np.dtype('int64').kind                                                                                          
'i'
>>> np.dtype('float').kind                                                                                          
'f'
>>> np.dtype('half').kind                                                                                           
'f'

# But be weary of matching dtypes
>>> np.integer
<class 'numpy.integer'>
>>> np.dtype(np.integer)
dtype('int64')
>>> x[0].dtype == np.dtype(np.integer)
False

# Down these paths there be dragons:

# the .dtype attribute returns a kind of dtype, not a specific dtype
>>> isinstance(x[0].dtype, np.dtype)
True
>>> isinstance(x[0].dtype, np.uint64)
False  
>>> isinstance(x[0].dtype, np.dtype(np.uint64))
Traceback (most recent call last):
  File "<console>", line 1, in <module>
TypeError: isinstance() arg 2 must be a type or tuple of types
# yea, don't go there
>>> isinstance(x[0].dtype, np.int_)
False  # again, confusing the .dtype with a specific dtype


# Inequalities can be tricky, although they might
# work sometimes, try to avoid these idioms:

>>> x[0].dtype <= np.dtype(np.uint64)
True
>>> x[0].dtype <= np.dtype(np.float)
True
>>> x[0].dtype <= np.dtype(np.half)
False  # just when things were going well
>>> x[0].dtype <= np.dtype(np.float16)
False  # oh boy
>>> x[0].dtype == np.int
False  # ya, no luck here either
>>> x[0].dtype == np.int_
False  # or here
>>> x[0].dtype == np.uint64
True  # have to end on a good note!
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.