Reputation: 455
I have a function that looks as following:
import numpy as np
def test() -> None:
a = map(np.radians, (1.,2.,np.array([1,2,3])))
Evaluating this with mypy returns the error message
error: Argument 1 to "map" has incompatible type "ufunc"; expected "Callable[[object], Any]"
Using only floats or only arrays as the input list for map
poses no problem here, the issue arises when the input list/tuple contains objects of both types. At runtime this poses no problem either.
How can I modify this function to satisfy mypy's requirements and make it typesafe?
Upvotes: 3
Views: 429
Reputation: 52
I don't know if it was intentional, but you didn't use dots in the array.
import numpy as np
def test() -> None:
a = map(np.radians, (1.,2.,np.array([1.,2.,3.])))
Upvotes: 0
Reputation: 3884
The problem here is that mypy infers the type of the elements of (1., 2., np.array([1,2,3]))
as object
(not as Union[float, np.ndarray]
as you'd hope here), which then is incompatible with np.radians
.
What you can do as a workaround is giving your tuple/list an explicit type that is compatible with both the tuple/list and the argument of np.radians
. E.g.:
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)
There is an open mypy github issue that seems similar, though maybe not exactly the same: python/mypy#6697.
Upvotes: 2
Reputation: 682
With all due respect, the right solution is to tell MyPy to ignore this line.
import numpy as np
def test() -> None:
a = map(np.radians, (1.,2.,np.array([1.,2.,3.]))) # type: ignore
PS: You always have the very inadvisable option to edit the numpy library and fix the call signature of _UFunc_Nin1_Nout1
to accept the object type (in addition to ArrayLike
). The edit below makes your mypy error message go away.
--- 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: ...
References
type: ignore
is a part of PEP484 for a reason._UFunc_Nin1_Nout
, https://github.com/numpy/numpy/blob/main/numpy/typing/_ufunc.pyiUpvotes: 0