评估 numpy.radians 和 float/array 输入元素的类型提示
Evaluating typehints for numpy.radians and float/array input elements
我有一个如下所示的函数:
import numpy as np
def test() -> None:
a = map(np.radians, (1.,2.,np.array([1,2,3])))
用 mypy 评估这个 returns 错误信息
error: Argument 1 to "map" has incompatible type "ufunc"; expected "Callable[[object], Any]"
仅使用浮点数或数组作为 map
的输入列表在这里没有问题,当输入 list/tuple 包含两种类型的对象时就会出现问题。在运行时这也没有问题。
如何修改此函数以满足 mypy 的要求并使其类型安全?
恕我直言,正确的解决方案是让 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
这里的问题是 mypy 将 (1., 2., np.array([1,2,3]))
的元素类型推断为 object
(而不是你希望的 Union[float, np.ndarray]
),这与np.radians
.
您可以做的解决方法是为您的 tuple/list 提供一个与 tuple/list 和 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)
有一个开放的 mypy github 问题看起来很相似,但也许
不完全相同:python/mypy#6697.
不知道是不是故意的,你没有在数组中使用点。
import numpy as np
def test() -> None:
a = map(np.radians, (1.,2.,np.array([1.,2.,3.])))
我有一个如下所示的函数:
import numpy as np
def test() -> None:
a = map(np.radians, (1.,2.,np.array([1,2,3])))
用 mypy 评估这个 returns 错误信息
error: Argument 1 to "map" has incompatible type "ufunc"; expected "Callable[[object], Any]"
仅使用浮点数或数组作为 map
的输入列表在这里没有问题,当输入 list/tuple 包含两种类型的对象时就会出现问题。在运行时这也没有问题。
如何修改此函数以满足 mypy 的要求并使其类型安全?
恕我直言,正确的解决方案是让 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
这里的问题是 mypy 将 (1., 2., np.array([1,2,3]))
的元素类型推断为 object
(而不是你希望的 Union[float, np.ndarray]
),这与np.radians
.
您可以做的解决方法是为您的 tuple/list 提供一个与 tuple/list 和 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)
有一个开放的 mypy github 问题看起来很相似,但也许 不完全相同:python/mypy#6697.
不知道是不是故意的,你没有在数组中使用点。
import numpy as np
def test() -> None:
a = map(np.radians, (1.,2.,np.array([1.,2.,3.])))