Skip to content

TYP: ndarray.item never typechecks #27977

Closed

Description

@jonathanberthias

Describe the issue:

In version 2.2.0, I have been completely unable to type the return value of a call to ndarray.item() which does not fail type checking. I have tried both MyPy and Pyright.

Am I doing something wrong here? Or is it an issue with the type checker(s)? It seems they don't even see all the overloads:

numpy/numpy/__init__.pyi

Lines 2111 to 2122 in a2012ad

@overload # special casing for `StringDType`, which has no scalar type
def item(self: ndarray[Any, dtypes.StringDType], /) -> str: ...
@overload
def item(self: ndarray[Any, dtypes.StringDType], arg0: SupportsIndex | tuple[SupportsIndex, ...] = ..., /) -> str: ...
@overload
def item(self: ndarray[Any, dtypes.StringDType], /, *args: SupportsIndex) -> str: ...
@overload # use the same output type as that of the underlying `generic`
def item(self: _HasShapeAndDTypeWithItem[Any, _T], /) -> _T: ...
@overload
def item(self: _HasShapeAndDTypeWithItem[Any, _T], arg0: SupportsIndex | tuple[SupportsIndex, ...] = ..., /) -> _T: ...
@overload
def item(self: _HasShapeAndDTypeWithItem[Any, _T], /, *args: SupportsIndex) -> _T: ...

Reproduce the code example:

import numpy as np


def f(x: np.ndarray[tuple[int], np.double]) -> float:
    return x.item()


def g(x: np.ndarray[tuple[int], np.str_]) -> str:
    return x.item()

Error message:

/dev/np_typing.py
  /dev/np_typing.py:4:33 - error: Type "double" cannot be assigned to type variable "_DType_co@ndarray"
    Type "double" is not assignable to upper bound "dtype[Any]" for type variable "_DType_co@ndarray"
      "floating[_NBitDouble]" is not assignable to "dtype[Any]" (reportInvalidTypeArguments)
  /dev/np_typing.py:5:14 - error: Cannot access attribute "item" for class "ndarray[tuple[int], double]"
    Could not bind method "item" because "ndarray[tuple[int], double]" is not assignable to parameter "self"
      "ndarray[tuple[int], double]" is not assignable to "ndarray[Any, StringDType]"
        Type parameter "_DType_co@ndarray" is covariant, but "double" is not a subtype of "StringDType"
          "floating[_NBitDouble]" is not assignable to "StringDType"
    Could not bind method "item" because "ndarray[tuple[int], double]" is not assignable to parameter "self"
      "ndarray[tuple[int], double]" is not assignable to "ndarray[Any, StringDType]"
        Type parameter "_DType_co@ndarray" is covariant, but "double" is not a subtype of "StringDType"
          "floating[_NBitDouble]" is not assignable to "StringDType" (reportAttributeAccessIssue)
  /dev/np_typing.py:8:33 - error: Type "str_" cannot be assigned to type variable "_DType_co@ndarray"
    Type "str_" is not assignable to upper bound "dtype[Any]" for type variable "_DType_co@ndarray"
      "str_" is not assignable to "dtype[Any]" (reportInvalidTypeArguments)
  /dev/np_typing.py:9:14 - error: Cannot access attribute "item" for class "ndarray[tuple[int], str_]"
    Could not bind method "item" because "ndarray[tuple[int], str_]" is not assignable to parameter "self"
      "ndarray[tuple[int], str_]" is not assignable to "ndarray[Any, StringDType]"
        Type parameter "_DType_co@ndarray" is covariant, but "str_" is not a subtype of "StringDType"
          "str_" is not assignable to "StringDType"
    Could not bind method "item" because "ndarray[tuple[int], str_]" is not assignable to parameter "self"
      "ndarray[tuple[int], str_]" is not assignable to "ndarray[Any, StringDType]"
        Type parameter "_DType_co@ndarray" is covariant, but "str_" is not a subtype of "StringDType"
          "str_" is not assignable to "StringDType" (reportAttributeAccessIssue)
4 errors, 0 warnings, 0 informations

Python and NumPy Versions:

2.2.0
3.11.10 (main, Sep 7 2024, 01:03:31) [GCC 11.4.0]

Type-checker version and settings:

pyright 1.1.390 with default settings

Additional typing packages.

No response

Activity

  1. changed the title [-]TYP: `ndarray.item` never matches[/-] [+]TYP: `ndarray.item` never typechecks[/+] on Dec 11, 2024
  2. jorenham commented on Dec 19, 2024

    @jorenham
    Member

    Reproduce the code example:

    import numpy as np
    
    
    def f(x: np.ndarray[tuple[int], np.double]) -> float:
        return x.item()
    
    
    def g(x: np.ndarray[tuple[int], np.str_]) -> str:
        return x.item()

    This is invalid: the 2nd type parameter of np.ndarray is bound to np.dtype, so it should instead be:

    import numpy as np
    
    
    def f(x: np.ndarray[tuple[int], np.dtype[np.double]]) -> float:
        return x.item()
    
    
    def g(x: np.ndarray[tuple[int], np.dtype[np.str_]]) -> str:
        return x.item()

    which is accepted by both mypy and pyright


    Oh and quick tip, np.float64 is almost always the same as np.double, but np.float64 has better annotations, for instance it actually has float as a supertype, whereas np.double doesn't.

  3. added
    57 - Close?Issues which may be closable unless discussion continued
    on Dec 19, 2024
  4. jonathanberthias commented on Dec 20, 2024

    @jonathanberthias
    Author

    Awesome thanks! I guess that I just tried to replace NDArray[np.str_] with ndarray[Shape, np.str_], and I didn't notice that NDArray also added the dtype for me. Thanks a lot for your help!

  5. removed
    57 - Close?Issues which may be closable unless discussion continued
    on Dec 20, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions