You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
[...]/issue_27965.pyi:3: note: Revealed type is "numpy.ndarray[tuple[builtins.int], numpy.dtype[numpy.float64]]"
[...]/issue_27965.pyi:4: note: Revealed type is "numpy.ndarray[builtins.tuple[builtins.int, ...], numpy.dtype[numpy.floating[Any]]]"
relevant pyright output:
[...]/issue_27965.pyi:3:13 - information: Type of "x := np.zeros(1)" is "ndarray[tuple[int], dtype[float64]]"
[...]/issue_27965.pyi:4:13 - information: Type of "x / 1" is "ndarray[tuple[int, ...], dtype[floating[Any]]]"
The np.zeros(1) is inferred by both mypy and pyright as a ndarray with 1-d shape and a dtype of float64. This is correct in the most accurate way that's (reasonably) possible.
But np.zeros(1) / 1 isn't as precisely typed, and is inferred as ndarray with ?-d shape and a dtype of floating.
Now the problem emerges when we do x = x / 1, which means we're assigning ndarray[tuple[int, ...], floating] to ndarray[(int), float64]. But this is invalid, because
tuple[int, ...] isn't assignable to tuple[int]
floating isn't assignable to float64 ()
This is because we can't assign something less specific to something more specific, just like you can't assign int to a bool.
But if we flip the LHS and RHS, then it actually is allowed. So in the same way that bool is assignable to int, tuple[int] is assignable to tuple[int, ...] and float64 is assignable to floating.
We can use this to create a very clean workaround to this issue:
Note that this workaround is only required for mypy users: Pyright infers the type of x as ndarray[tuple[int, ...], dtype[floating]], because it looks at more than one line of code at a time, and isn't "greedy" (algorithmically speaking) like mypy is.
Activity
jorenham commentedon Dec 19, 2024
this example shows why type-checkers reject the
x = x / 1from your example"relevant mypy output:
relevant pyright output:
The
np.zeros(1)is inferred by both mypy and pyright as andarraywith 1-d shape and a dtype offloat64. This is correct in the most accurate way that's (reasonably) possible.But
np.zeros(1) / 1isn't as precisely typed, and is inferred asndarraywith ?-d shape and a dtype offloating.Now the problem emerges when we do
x = x / 1, which means we're assigningndarray[tuple[int, ...], floating]tondarray[(int), float64]. But this is invalid, becausetuple[int, ...]isn't assignable totuple[int]floatingisn't assignable tofloat64()This is because we can't assign something less specific to something more specific, just like you can't assign
intto abool.But if we flip the LHS and RHS, then it actually is allowed. So in the same way that
boolis assignable toint,tuple[int]is assignable totuple[int, ...]andfloat64is assignable tofloating.We can use this to create a very clean workaround to this issue:
Note that this workaround is only required for mypy users: Pyright infers the type of
xasndarray[tuple[int, ...], dtype[floating]], because it looks at more than one line of code at a time, and isn't "greedy" (algorithmically speaking) like mypy is.