dmmpie
dmmpie

Reputation: 455

Evaluating typehints for numpy.radians and float/array input elements

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

Answers (3)

Pascal Arsenal
Pascal Arsenal

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

mihi
mihi

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

user23952
user23952

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

Upvotes: 0

Related Questions