8000 BUG: Type annotations for ufuncs discard dtype information in the return type · Issue #21907 · numpy/numpy · GitHub
[go: up one dir, main page]

Skip to content

BUG: Type annotations for ufuncs discard dtype information in the return type #21907

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
0xjc opened this issue Jul 2, 2022 · 1 comment
Open

Comments

@0xjc
Copy link
0xjc commented Jul 2, 2022

Describe the issue:

When passing in an array of known dtype, some of the numpy functions discard some or all of the dtype information in the return type. In the example below, np.sum and np.sort properly preserve the dtype. np.mean, np.median, np.linalg.norm preserve that the dtype was floating but not the specific dtype. np.log and np.sin discard the entire dtype.

Since the discarded types are replaced by Any, this means that further code that uses the result of these functions may lose useful type checks resulting in false negatives, unless the user manually narrows the result back to the known dtype.

Reproduce the code example:

from typing import TYPE_CHECKING
import numpy as np


x = np.array([1.0, 2.0], dtype=np.float64)

y1 = np.sum(x)
y2 = np.mean(x)
y3 = np.median(x)
y4 = np.linalg.norm(x)

z1 = np.sort(x)
z2 = np.log(x)
z3 = np.sin(x)


if TYPE_CHECKING:
    reveal_locals()
    """
    Type of "x" is "ndarray[Any, dtype[floating[_64Bit]]]"
    Type of "y1" is "floating[_64Bit]"
    Type of "y2" is "floating[Any]"
    Type of "y3" is "floating[Any]"
    Type of "y4" is "floating[Any]"
    Type of "z1" is "ndarray[Any, dtype[floating[_64Bit]]]"
    Type of "z2" is "ndarray[Any, dtype[Any]]"
    Type of "z3" is "ndarray[Any, dtype[Any]]"
    """

# Actual types at runtime
print(
    f"""
               x  dtype={x.dtype}
        np.sum(x)  type={type(y1).__name__}
       np.mean(x)  type={type(y2).__name__}
     np.median(x)  type={type(y3).__name__}
np.linalg.norm(x)  type={type(y4).__name__}
       np.sort(x) dtype={z1.dtype}
        np.log(x) dtype={z2.dtype}
        np.sin(x) dtype={z3.dtype}
"""
)
"""
               x  dtype=float64
        np.sum(x)  type=float64
       np.mean(x)  type=float64
     np.median(x)  type=float64
np.linalg.norm(x)  type=float64
       np.sort(x) dtype=float64
        np.log(x) dtype=float64
        np.sin(x) dtype=float64
"""

NumPy/Python version information:

Python 3.8.10
numpy 1.23.0

@0xjc 0xjc added the 00 - Bug label Jul 2, 2022
@BvB93 BvB93 changed the title BUG: Type annotations for many functions discard dtype information in the return type BUG: Type annotations for ufuncs discard dtype information in the return type Jul 6, 2022
@BvB93
Copy link
Member
BvB93 commented Jul 6, 2022

Sub-issue of #19252

Basic dtype typing support has been implemented for most functions, but notable in its absence are the ufuncs. I suspect that, without resorting to mypy plugins, there is no trivial way of creating the relevant annotations here without treating all universal functions as (private) np.ufunc subtypes, each with their individually tailored annotations.

To a certain extent this is already done for the various nin/nout combinations, but this would then have to be repeated for all ufuncs.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants
0