【问题标题】:How to identify numpy types in python?如何识别python中的numpy类型?
【发布时间】:2012-09-16 04:10:13
【问题描述】:

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

我意识到这个问题违背了鸭子类型的哲学,但想法是确保一个函数(使用 scipy 和 numpy)永远不会返回一个 numpy 类型,除非它被一个 numpy 类型调用。 This comes up in the solution to another question, 但我认为确定对象是否具有 numpy 类型的一般问题与应该将它们分开的原始问题相距甚远。

【问题讨论】:

  • 一个问题:如果你(或者说,scipy)定义了一个子类化 numpy 类型的类型,这应该算吗? (我相信你不能在 Python 中子类化 numpy 类型,但你可以在 C 模块中,而且我认为你也可以在 PyPy 中子类化 numpypy 类型......所以这可能没关系,但它可以不是不可想象的。)
  • 我没想到;基本上你的评论指出这个问题比预期的要难。老实说,这种高层次的考虑对我的情况来说太过分了。对于通用且可移植的答案,我会说只要定义了行为就可以了。

标签: python numpy duck-typing dynamic-typing


【解决方案1】:

使用内置的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 的类型?
  • 如果你想要 numpy.* 中的任何东西,你只需遍历模块的父包。 (此时,您显然希望将其包装在一个函数中。)如果您希望 pandas DataFrames 算作 numpyish,请添加一个 or 来测试它。等等。关键是,当你想做一些像松散的手动类型切换这样不寻常的事情时,你必须知道你实际要求的是什么,但是一旦你知道了,它就很容易实现。
  • 这个解决方案看起来很不合python,依赖于隐藏的属性。但也许这只是口味问题?
  • @j08lue 它们不是隐藏属性,而是记录在案的特殊属性。尽管如此,它是非pythonic,但我认为这是问题所固有的。 (而且我认为 Python 的优势在于,当你想做一些该语言不鼓励做的事情时,最好的解决方案通常看起来丑陋到足以让人觉得你正在做的事情通常是个坏主意。)
【解决方案2】:

我想出的解决办法是:

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

但是,it's not 100% clear 保证所有 numpy 类型都是 np.ndarraynp.generic,这可能不是版本健壮的。

【讨论】:

  • 我想你可以过滤 dir(numpy) 类型和内置函数(和类,但我认为它没有)并使用它来生成一个元组到 isinstance 反对,这将要健壮。 (我相信您可以将内置函数传递给 isinstance,无论它们实际上是否是类型构造函数,但您必须检查一下。)
  • 是的,它们都应该是这两个 AFAIK 的子类。
  • @seberg 谢谢。现在看来肯定是这样,但是 python 文档isn't very clear on this 将来可能会发生变化。
【解决方案3】:

老问题,但我想出了一个明确的答案,举个例子。保持问题新鲜不会有什么坏处,因为我遇到了同样的问题并且没有找到明确的答案。关键是确保你已经导入了numpy,然后运行isinstance bool。虽然这看起来很简单,但如果您正在对不同的数据类型进行一些计算,那么这个小检查可以作为您开始一些 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)

【讨论】:

    【解决方案4】:

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

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

    【讨论】:

    • +1。如果您实际上正在寻找“是numpy 类型”之外的其他内容,并且可以定义该内容是什么,那么这比其他答案更好。在大多数情况下,您应该寻找可以定义的特定内容。
    【解决方案5】:

    要获取类型,请使用内置的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 中运行的。对于交互式使用和快速测试来说非常方便。)

    【讨论】:

    • 这行得通,但是如果你定义了一个名为“numpygroup”的类型,你会得到误报。此外,如果可以避免依赖于类型的字符串表示形式,那也是个坏主意——在这种情况下,你可以。请查看它的模块。
    • 使用模块确实是更好的解决方案。
    • 可以使用正则表达式
    • @Omkaar.K 正则表达式可以用来做什么?以稍微复杂的方式进行完全相同的检查?
    • @abamert "Could" 就是我所说的,对于像这样的简单任务,正则表达式可能看起来很复杂,但它对于大型字符串处理任务非常有用,所以学习它不是一个坏主意.我想你已经知道了,因为你的作品集将你描绘成一名高级程序员?
    【解决方案6】:

    请注意,type(numpy.ndarray) 本身就是 type,请注意布尔类型和标量类型。如果它不直观或不简单,请不要气馁,一开始会很痛苦。

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

    >>> 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!
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-01-18
      • 1970-01-01
      • 1970-01-01
      • 2015-03-21
      • 1970-01-01
      • 1970-01-01
      • 2015-11-25
      • 1970-01-01
      相关资源
      最近更新 更多