输入numpy.ndarray的提示/注释(PEP 484)

Ino*_*non 47 numpy type-hinting strong-typing multidimensional-array python-3.5

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

现在,我正在使用打字.但是,如果有更具体的内容会更好.

例如,如果numpy人为其array_like对象类添加了一个类型别名.更好的是,在dtype级别实现支持,以便支持其他对象,以及ufunc.

Jas*_*sha 84

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


来自Numpy 1.21 文档
numpy.typing.NDArray = numpy.ndarray[typing.Any, numpy.dtype[+ScalarType]]
Run Code Online (Sandbox Code Playgroud)

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

可在运行时用于输入具有给定数据类型和未指定形状的数组。

例子:

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

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

  • 我只是想知道如果我在类型提示中使用 ndarray 而不是 NDArray 会怎么样?有什么根本区别吗? (4认同)
  • 看看[`NDarray`的定义](https://github.com/numpy/numpy/blob/b235f9e701e14ed6f6f6dcba885f7986a833743f/numpy/typing/_generic_alias.py#L201-L208),似乎(1)有*是*运行时的差异(因为“NDArray”是一个通用别名,而“ndarray”是一个类),以及(2)在类型检查时(例如使用 mypy、pyright 等时),“NDarray[”之间应该没有区别Foo]` 和 `np.ndarray[Any, np.dtype[Foo]]`。 (3认同)
  • “np.ndarray[...]”类型提示的第一个参数是什么?为什么在所有示例中它都是“Any”? (3认同)

hpa*_*ulj 18

它看起来像typing模块开发于:

https://github.com/python/typing

numpy存储库位于

https://github.com/numpy/numpy

可以跟踪Python错误和提交

http://bugs.python.org/

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

cython有一种注释形式,用于生成有效的C代码.


您引用了文档中的array-like段落numpy.请注意其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)
Run Code Online (Sandbox Code Playgroud)

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

def foo(x: np.ndarray) -> np.ndarray:
Run Code Online (Sandbox Code Playgroud)

作品.当然,如果你的函数最终调用了一些numpy传递其参数的函数asanyarray(尽可能多),这样的注释将是不完整的,因为你的输入可能是a list,或np.matrix等等.


在评估此问题和答案时,请注意日期.484当时是一个相对较新的PEP,并且仍在开发中使用它来编写标准Python的代码.但看起来提供的链接仍然有效.

  • 我已将此答案标记为已接受的答案,但为了完整性,我选择了后者(在我自己的代码中使用Numpy进行类型提示).我全都是Duck Typing,但是当你**可以**提供静态类型信息时,我不明白为什么你不会,如果只是静态代码分析(PyCharm确实警告不兼容的类型).谢谢,@ hpaulj! (3认同)
  • 形状怎么样?我可以添加提示,如 def blah() -&gt; np.ndarray(785): 但我不能添加第二个维度,如 -&gt; np.ndarray(785, 10)。拥有形状提示非常有帮助,并且可以使我的代码中生成不同维度数组的多个函数变得清晰。 (2认同)

Epi*_*Adv 10

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


Pet*_*ter 9

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

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)])))

Run Code Online (Sandbox Code Playgroud)

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

在此处输入图片说明

  • 这是好东西,谢谢分享。然而,nptyping 包(https://github.com/ramonhagenaars/nptyping)似乎相当概括了这一点。 (3认同)

Bac*_*ics 5

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

  • 如何使用 DataShape?该文档详细介绍了 DataShape 的功能,但我并没有真正找到任何具体示例来说明如何将其用于 Python 中的类型提示。 (2认同)
  • 这只是一个仅限链接的答案。[最好](​​https://meta.stackexchange.com/q/8231/378331)在这里添加这个库的使用示例,并提供参考链接。 (2认同)
  • 虽然此链接可以回答问题,但最好在此处包含答案的基本部分并提供链接以供参考。如果链接页面发生更改,仅链接的答案可能会变得无效。- [来自评论](/review/low-quality-posts/26986820) (2认同)