【问题标题】:Type hinting / annotation (PEP 484) for numpy.ndarraynumpy.ndarray 的类型提示/注释 (PEP 484)
【发布时间】:2023-03-31 09:26:01
【问题描述】:

是否有人为特定的numpy.ndarray 类实现了类型提示?

现在,我使用的是typing.Any,但如果有更具体的内容会更好。

例如,如果 NumPy 人员为他们的 array_like 对象类添加了 type alias。更好的是,在dtype 级别实现支持,以便支持其他对象以及ufunc

【问题讨论】:

  • pypi.python.org/pypi/plac 可以使用 Py3 注释 - 填充 argparse 解析器。对于 Py2,它使用装饰器创建类似的 annocation 数据库。
  • typing 是 Py 3.5 的新手。许多 numpy 用户仍在使用 Py2。我的系统上有 3.5,但我没有为它安装 numpynumpy 开发人员不会为 Python 的前沿添加功能(@ 运算符除外)
  • numpy 维护在 github 存储库中。看issuespull requests;注册并提交您自己的问题。可能还有另一个讨论开发问题的论坛,但我看的最多的是github 问题。
  • 对于任何调查此问题的人 - 看起来这里有一个相关的解决方案:stackoverflow.com/questions/52839427/…
  • > 现在有...@Jasha 这张票是 4.5 年前由我作为 OP 开的。

标签: python python-3.x numpy type-hinting python-typing


【解决方案1】:

查看DataShape。它使用数据类型以及一些语法来确定输入和输出数组的大小。

【讨论】:

  • 所以 DataShape 是 Numpy 替代品?不完全是我的想法,因为我使用的是 SciPy,它需要 Numpy,明确地。
  • DataShape 是一个描述。目前没有正式的函数注释,但到目前为止,如果你要构建函数注释,这是我见过的关于 Numpy 类型的最佳描述。是的,我建议在将函数注释引入 numpy 源之前创建一个新的模块名称并将其用作概念证明。
  • 如何使用 DataShape?该文档详细说明了 DataShape 可以做什么,但我并没有真正找到任何具体示例来说明它如何用于 Python 中的类型提示。
  • 这只是一个仅链接的答案。 It would be preferable在此添加该库的使用示例,并提供链接供参考。
  • 感谢您的反馈。我可以在这周晚些时候更新。
【解决方案2】:

更新

检查最近的 numpy 版本是否有新的 typing 模块

https://numpy.org/doc/stable/reference/typing.html#module-numpy.typing

过时的答案

看起来typing 模块是在以下位置开发的:

https://github.com/python/typing

numpy 的主要存储库位于

https://github.com/numpy/numpy

可以在以下位置跟踪 Python 错误和提交

http://bugs.python.org/

添加功能的通常方法是分叉主存储库,开发该功能直到它是防弹的,然后提交一个拉取请求。显然,在流程的各个阶段,您都需要其他开发人员的反馈。如果您不能自己进行开发,那么您必须说服其他人这是一个有价值的项目。

cython 有一种注解形式,用于生成高效的C 代码。


您在numpy 文档中引用了array-like 段落。注意它的typing 信息:

确定对象是否可以使用 array() 转换为 numpy 数组的一种简单方法是简单地以交互方式尝试它,看看它是否有效! (Python 方式)。

换句话说,numpy 开发人员拒绝被牵制。他们没有或不能用文字描述哪些类型的对象可以或不能转换为np.ndarray

In [586]: np.array({'test':1})   # a dictionary
Out[586]: array({'test': 1}, dtype=object)

In [587]: np.array(['one','two'])  # a list
Out[587]: 
array(['one', 'two'], 
      dtype='<U3')

In [589]: np.array({'one','two'})  # a set
Out[589]: array({'one', 'two'}, dtype=object)

对于你自己的函数,像这样的注释

def foo(x: np.ndarray) -> np.ndarray:

有效。当然,如果您的函数最终调用了一些通过asanyarray 传递其参数的numpy 函数(正如许多人所做的那样),那么这样的注释将是不完整的,因为您的输入可能是listnp.matrix 等.


在评估这个问题和答案时,请注意日期。 484 在当时是一个相对较新的 PEP,将其用于标准 Python 的代码仍在开发中。但看起来提供的链接仍然有效。

【讨论】:

  • 您正在使用什么软件、编辑器或解释器来使用annotations?据我所知,在普通的 Python 3 中,一个函数得到一个 __annotations__ 字典,但解释器对它什么也不做。
  • 您希望将typing 注释添加到现有的numpy 函数(包括np.array)中,还是只希望将注释添加到您自己的函数中更容易的类型?
  • 我已将此答案标记为已接受的答案,但为了完整起见,我选择后者(在我自己的代码中输入提示,它使用 Numpy)。我完全赞成 Duck Typing,但是当您 可以 提供静态类型信息时,我不明白您为什么不这样做,如果只是用于静态代码分析(PyCharm 确实会警告不兼容的类型)。谢谢,@hpaulj!
  • 因为打字模块只是提供提示,我创建了两个帮助标签纯粹是为了便于阅读,并注意它没有通过 mypy 静态类型检查。 def Vector(np_arr): return np_arr.ndim == 1 def Matrix(np_arr): return np_arr.ndim &gt; 1 。希望,它可以帮助某人。
  • 形状怎么样?我可以添加诸如 def blah() -> np.ndarray(785) 之类的提示:但我不能添加第二个维度,例如 -> np.ndarray(785, 10)。有一个形状提示非常有帮助,并且可以使我的代码中产生不同维度数组的多个函数更加清晰。
【解决方案3】:

我所做的只是将其定义为

Dict[Tuple[int, int], TYPE]

例如,如果你想要一个浮点数组,你可以这样做:

a = numpy.empty(shape=[2, 2], dtype=float) # type: Dict[Tuple[int, int], float]

从文档的角度来看,这当然不准确,但是为了分析正确的用法并使用 pyCharm 正确完成,它非常有用!

【讨论】:

  • 这比使用np.ndarray 作为类型更糟糕
【解决方案4】:

nptyping 为指定 numpy 类型提示增加了很多灵活性。

【讨论】:

    【解决方案5】:

    在我公司,我们一直在使用:

    from typing import TypeVar, Generic, Tuple, Union, Optional
    import numpy as np
    
    Shape = TypeVar("Shape")
    DType = TypeVar("DType")
    
    class Array(np.ndarray, Generic[Shape, DType]):
        """  
        Use this to type-annotate numpy arrays, e.g. 
            image: Array['H,W,3', np.uint8]
            xy_points: Array['N,2', float]
            nd_mask: Array['...', bool]
        """
        pass
    
    def compute_l2_norm(arr: Array['N,2', float]) -> Array['N', float]:
        return (arr**2).sum(axis=1)**.5
    
    print(compute_l2_norm(arr = np.array([(1, 2), (3, 1.5), (0, 5.5)])))
    
    

    我们实际上有一个 MyPy 检查器来检查形状是否有效(我们应该在某个时候发布)。唯一的问题是它不会让 PyC​​harm 高兴(即你仍然会收到讨厌的警告行):

    【讨论】:

    • MyPy 检查器有什么更新吗?很想将它集成到我的环境中
    • 这是好东西,谢谢分享。然而,nptyping 包 (github.com/ramonhagenaars/nptyping) 似乎在很大程度上概括了这一点。
    【解决方案6】:

    Numpy 1.21 包含一个带有 NDArray 泛型类型的 numpy.typing 模块。


    来自Numpy 1.21 docs
    numpy.typing.NDArray = numpy.ndarray[typing.Any, numpy.dtype[+ScalarType]
    

    np.ndarray[Any, np.dtype[+ScalarType]] 的通用版本。

    可在运行时用于键入具有给定 dtype 和未指定形状的数组。

    示例:

    >>> import numpy as np
    >>> import numpy.typing as npt
    
    >>> print(npt.NDArray)
    numpy.ndarray[typing.Any, numpy.dtype[+ScalarType]]
    
    >>> print(npt.NDArray[np.float64])
    numpy.ndarray[typing.Any, numpy.dtype[numpy.float64]]
    
    >>> NDArrayInt = npt.NDArray[np.int_]
    >>> a: NDArrayInt = np.arange(10)
    
    >>> def func(a: npt.ArrayLike) -> npt.NDArray[Any]:
    ...     return np.array(a)
    

    截至 2021 年 11 月 10 日,根据numpy/numpy#16544,对形状的支持仍在进行中。

    【讨论】:

      猜你喜欢
      • 2016-10-26
      • 2018-03-01
      • 2019-03-21
      • 2019-10-07
      • 1970-01-01
      • 2018-11-05
      • 2016-08-03
      • 1970-01-01
      相关资源
      最近更新 更多