评估 numpy.radians 和浮点/数组输入元素的类型提示

Posted

技术标签:

【中文标题】评估 numpy.radians 和浮点/数组输入元素的类型提示【英文标题】:Evaluating typehints for numpy.radians and float/array input elements 【发布时间】:2022-01-14 10:53:57 【问题描述】:

我有一个如下所示的函数:

import numpy as np

def test() -> None:
    a = map(np.radians, (1.,2.,np.array([1,2,3])))

用 mypy 计算会返回错误信息

error: Argument 1 to "map" has incompatible type "ufunc"; expected "Callable[[object], Any]"

仅使用浮点数或仅数组作为map 的输入列表在这里没有问题,当输入列表/元组包含两种类型的对象时就会出现问题。在运行时,这也没有问题。 如何修改此函数以满足 mypy 的要求并使其类型安全?

【问题讨论】:

喜欢def test() -> None: f = np.radians # type: Any; a = map(f, (1., 2., np.array([1, 2, 3])))?你只是想摆脱错误信息? @ThomasWeller 有没有更好的方法来做到这一点?这是 numpy 固有的错误还是我可以正确完成的错误? 就个人而言,我正在使用 Pycharm。它也使用类型提示并给出警告,但它不像 mypy 那样严格。你为什么使用mypy?编写更好的代码还是由您的雇主强制执行? @ThomasWeller 我们有一个软件,我们想让它类型安全,并为此目的使用 mypy。你会建议我们如何处理这个问题?为此添加新行或根本不注释整个函数是否有意义? 抱歉,我不是这方面的专家。让我们拭目以待其他人怎么说。我认为以下几点:a)您知道它不会出现运行时错误 b)它似乎更像是一个 numpy 问题,它如何声明方法而不是您的问题。例如。 def test() -> None: f = lambda x: np.radians(x); a = map(f, (1., 2., np.array([1, 2, 3]))) 也不会有 mypy 报告,但您可能会失去性能(矢量化)。就 Sp 个人而言,我可能会选择# type: ignore 整行。 【参考方案1】:

这里的问题是 mypy 将 (1., 2., np.array([1,2,3])) 的元素类型推断为 object(而不是您希望在这里的 Union[float, np.ndarray]),这与 np.radians 不兼容。

您可以做的一种解决方法是为您的元组/列表提供一个与元组/列表和np.radians 的参数兼容的显式类型。例如:

from typing import Sequence, Union
import numpy as np

def test() -> None:
    x: Sequence[Union[float, np.ndarray]] = (1., 2., np.array([1,2,3]))
    a = map(np.radians, x)

有一个 open mypy github issue 看起来很相似,但也许 不完全相同:python/mypy#6697。

【讨论】:

【参考方案2】:

恕我直言,正确的解决方案是告诉 MyPy 忽略这一行。

import numpy as np

def test() -> None:
    a = map(np.radians, (1.,2.,np.array([1.,2.,3.]))) # type: ignore

PS:您总是有非常不明智的选择来编辑 numpy 库并修复 _UFunc_Nin1_Nout1 的调用签名以接受对象类型(除了 ArrayLike)。下面的编辑使您的 mypy 错误消息消失。

--- a/typing/_ufunc.pyi
+++ b/typing/_ufunc.pyi
@@ -86,21 +86,21 @@ class _UFunc_Nin1_Nout1(ufunc, Generic[_NameType, _NTypes, _IDType]):
         casting: _Casting = ...,
         order: _OrderKACF = ...,
         dtype: DTypeLike = ...,
         subok: bool = ...,
         signature: Union[str, _2Tuple[Optional[str]]] = ...,
         extobj: List[Any] = ...,
     ) -> Any: ...
     @overload
     def __call__(
         self,
-        __x1: ArrayLike,
+        __x1: ArrayLike | object,
         out: Union[None, NDArray[Any], Tuple[NDArray[Any]]] = ...,
         *,
         where: Optional[_ArrayLikeBool_co] = ...,
         casting: _Casting = ...,
         order: _OrderKACF = ...,
         dtype: DTypeLike = ...,
         subok: bool = ...,
         signature: Union[str, _2Tuple[Optional[str]]] = ...,
         extobj: List[Any] = ...,
     ) -> NDArray[Any] | Any: ...

参考文献

Readthedocs 上的 MyPy 文档,MyPy Common Issues and Solutions, Spurious errors and locally silencing the checker。 type: ignore 是 PEP484 的一部分是有原因的。 Numpy _ufunc.py 声明了有问题的类型规范_UFunc_Nin1_Nout、https://github.com/numpy/numpy/blob/main/numpy/typing/_ufunc.pyi

【讨论】:

【参考方案3】:

我不知道是不是故意的,但你没有在数组中使用点。

import numpy as np

def test() -> None:
    a = map(np.radians, (1.,2.,np.array([1.,2.,3.])))

【讨论】:

以上是关于评估 numpy.radians 和浮点/数组输入元素的类型提示的主要内容,如果未能解决你的问题,请参考以下文章

如何在java中获取mp3流作为浮点数组

将 CString 转换为浮点数组

浮点代码的 g++ 优化开关

使用浮点 NumPy 数组进行比较和相关操作

浮点数组到字节数组和反之亦然

UWP流到浮点数组c#