-
-
Notifications
You must be signed in to change notification settings - Fork 11.1k
ENH: Add annotations to the last 8 functions in numpy.core.fromnumeric #16729
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
Changes from 2 commits
8a95c66
3bc51b8
62f26cf
5a42440
5c2dd87
c2e27c2
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -1231,3 +1231,113 @@ def amin( | |||||||||||||||
initial: _NumberLike = ..., | ||||||||||||||||
where: _ArrayLikeBool = ..., | ||||||||||||||||
) -> Union[number, ndarray]: ... | ||||||||||||||||
|
||||||||||||||||
# TODO: `np.prod()``: For object arrays `initial` does not necasarily | ||||||||||||||||
# have to be a numerical scalar. | ||||||||||||||||
# The only requirement is that it is compatible | ||||||||||||||||
# with the `.__mult__()` method(s) of the passed array's elements. | ||||||||||||||||
BvB93 marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||||||||
|
||||||||||||||||
# Note that the same holds for `np.sum()` and `.__add__()`. | ||||||||||||||||
BvB93 marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||||||||
|
||||||||||||||||
@overload | ||||||||||||||||
def prod( | ||||||||||||||||
a: _Number, | ||||||||||||||||
axis: Optional[_ShapeLike] = ..., | ||||||||||||||||
dtype: DtypeLike = ..., | ||||||||||||||||
out: Optional[ndarray] = ..., | ||||||||||||||||
keepdims: bool = ..., | ||||||||||||||||
initial: _NumberLike = ..., | ||||||||||||||||
where: _ArrayLikeBool = ..., | ||||||||||||||||
) -> _Number: ... | ||||||||||||||||
@overload | ||||||||||||||||
def prod( | ||||||||||||||||
a: ArrayLike, | ||||||||||||||||
axis: None = ..., | ||||||||||||||||
dtype: DtypeLike = ..., | ||||||||||||||||
out: Optional[ndarray] = ..., | ||||||||||||||||
keepdims: Literal[False] = ..., | ||||||||||||||||
initial: _NumberLike = ..., | ||||||||||||||||
where: _ArrayLikeBool = ..., | ||||||||||||||||
) -> number: ... | ||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I am assuming we are allowing number subtypes for one but not the other why is that ? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The key difference is that the first one is a To illustrate, in the first overload an arbitrary In the second overload we know that an instance of Lines 511 to 517 in 92665ab
As a workaround the latter case is now simply annotated as returning a There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. okay got it, if my understanding is correct, the functionality is exactly the same if we use number of _Number here (second overload), but it is something we want to change in the future ? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oh hang on, I'm actually confusing the issues pertaining The problem with returning >>> from typing import TypeVar
>>> import numpy as np
>>> from numpy.typing import ArrayLike
>>> T = TypeVar('T', bound=np.number)
>>> def func(a: ArrayLike[T]) -> T:
... pass If you're interested, see #16759 for more details. |
||||||||||||||||
@overload | ||||||||||||||||
def prod( | ||||||||||||||||
a: ArrayLike, | ||||||||||||||||
axis: Optional[_ShapeLike] = ..., | ||||||||||||||||
dtype: DtypeLike = ..., | ||||||||||||||||
BvB93 marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||||||||
out: Optional[ndarray] = ..., | ||||||||||||||||
keepdims: bool = ..., | ||||||||||||||||
initial: _NumberLike = ..., | ||||||||||||||||
where: _ArrayLikeBool = ..., | ||||||||||||||||
) -> Union[number, ndarray]: ... | ||||||||||||||||
def cumprod( | ||||||||||||||||
a: ArrayLike, | ||||||||||||||||
axis: Optional[int] = ..., | ||||||||||||||||
dtype: DtypeLike = ..., | ||||||||||||||||
BvB93 marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||||||||
out: Optional[ndarray] = ..., | ||||||||||||||||
) -> ndarray: ... | ||||||||||||||||
def ndim(a: ArrayLike) -> int: ... | ||||||||||||||||
def size(a: ArrayLike, axis: Optional[int] = ...) -> int: ... | ||||||||||||||||
@overload | ||||||||||||||||
def around( | ||||||||||||||||
a: _Number, decimals: int = ..., out: Optional[ndarray] = ... | ||||||||||||||||
) -> _Number: ... | ||||||||||||||||
@overload | ||||||||||||||||
def around( | ||||||||||||||||
a: _NumberLike, decimals: int = ..., out: Optional[ndarray] = ... | ||||||||||||||||
) -> number: ... | ||||||||||||||||
@overload | ||||||||||||||||
def around( | ||||||||||||||||
a: ArrayLike, decimals: int = ..., out: Optional[ndarray] = ... | ||||||||||||||||
) -> ndarray: ... | ||||||||||||||||
@overload | ||||||||||||||||
def mean( | ||||||||||||||||
a: ArrayLike, | ||||||||||||||||
axis: None = ..., | ||||||||||||||||
dtype: DtypeLike = ..., | ||||||||||||||||
out: Optional[ndarray] = ..., | ||||||||||||||||
keepdims: Literal[False] = ..., | ||||||||||||||||
) -> number: ... | ||||||||||||||||
@overload | ||||||||||||||||
def mean( | ||||||||||||||||
a: ArrayLike, | ||||||||||||||||
axis: Optional[_ShapeLike] = ..., | ||||||||||||||||
dtype: DtypeLike = ..., | ||||||||||||||||
out: Optional[ndarray] = ..., | ||||||||||||||||
keepdims: bool = ..., | ||||||||||||||||
) -> Union[number, ndarray]: ... | ||||||||||||||||
@overload | ||||||||||||||||
def std( | ||||||||||||||||
a: ArrayLike, | ||||||||||||||||
axis: None = ..., | ||||||||||||||||
dtype: DtypeLike = ..., | ||||||||||||||||
out: Optional[ndarray] = ..., | ||||||||||||||||
ddof: int = ..., | ||||||||||||||||
keepdims: Literal[False] = ..., | ||||||||||||||||
) -> number: ... | ||||||||||||||||
@overload | ||||||||||||||||
def std( | ||||||||||||||||
a: ArrayLike, | ||||||||||||||||
axis: Optional[_ShapeLike] = ..., | ||||||||||||||||
dtype: DtypeLike = ..., | ||||||||||||||||
out: Optional[ndarray] = ..., | ||||||||||||||||
ddof: int = ..., | ||||||||||||||||
keepdims: bool = ..., | ||||||||||||||||
) -> Union[number, ndarray]: ... | ||||||||||||||||
@overload | ||||||||||||||||
def var( | ||||||||||||||||
a: ArrayLike, | ||||||||||||||||
axis: None = ..., | ||||||||||||||||
dtype: DtypeLike = ..., | ||||||||||||||||
out: Optional[ndarray] = ..., | ||||||||||||||||
ddof: int = ..., | ||||||||||||||||
keepdims: Literal[False] = ..., | ||||||||||||||||
) -> number: ... | ||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This applies for most but not all functions in this patch with < 685C details-menu class="dropdown-menu dropdown-menu-sw show-more-popover color-fg-default" style="width:185px" src="" preload >
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Considering the widespread nature of this issue I'd propose to save it for a future maintenance pull request and fix it all at once (as there are already quite a few older annotated functions with There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In the meantime then, it would probably be a good idea to annotate these with There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As it turns out is fairly easy way to fix this: I have noticed some inconsistent behavior when using In [1]: import numpy as np
In [2]: np.__version__
Out[2]: '1.20.0.dev0+62f26cf'
In [3]: np.var(np.int64(1), out=np.zeros(()))
Out[3]: 0.0
In [4]: np.var(1, out=np.zeros(()))
Out[4]: array(0.)
In [5]: np.var([1], out=np.zeros(()))
Out[5]: array(0.)
In [6]: np.var(np.ones(1), out=np.zeros(()))
Out[6]: array(0.) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That is arguably a bug in There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Fixed as of 5a42440. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
I'll double check which (currently annotated) functions are affected by this this and create an issue afterwards (see #16734). |
||||||||||||||||
@overload | ||||||||||||||||
def var( | ||||||||||||||||
a: ArrayLike, | ||||||||||||||||
axis: Optional[_ShapeLike] = ..., | ||||||||||||||||
dtype: DtypeLike = ..., | ||||||||||||||||
out: Optional[ndarray] = ..., | ||||||||||||||||
ddof: int = ..., | ||||||||||||||||
keepdims: bool = ..., | ||||||||||||||||
) -> Union[number, ndarray]: ... |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -124,3 +124,31 @@ | |
np.amin(a, out=1.0) # E: No overload variant of "amin" matches argument type | ||
np.amin(a, initial=[1.0]) # E: No overload variant of "amin" matches argument type | ||
np.amin(a, where=[1.0]) # E: List item 0 has incompatible type | ||
|
||
np.prod(a, axis=1.0) # E: No overload variant of "prod" matches argument type | ||
np.prod(a, out=False) # E: No overload variant of "prod" matches argument type | ||
np.prod(a, keepdims=1.0) # E: No overload variant of "prod" matches argument type | ||
np.prod(a, initial=int) # E: No overload variant of "prod" matches argument type | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is legal for suitable a:
Or for an almost plausible use: >>> from ctypes import c_uint8
>>> shape = np.array([1, 2, 3])
>>> np.prod(shape.astype(object), initial=c_uint8)
# a ctypes array type
numpy.core.fromnumeric.c_ubyte_Array_1_Array_2_Array_3 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Incidentally, this also proves that the return type of There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
If I'm not mistaken this is limited to, the notoriously difficult to type, object arrays. The alternative would be to set There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
How so? Perhaps the compromise is to stick There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
That's actually a good point; I more or less conflated scalar with numerical scalar here.
I agree, I'll push an update in a bit. As for the future: What I've gathered is, in the case of object arrays, that There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Added in 3bc51b8. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
I wouldn't personally bother. Simply having |
||
np.prod(a, where=1.0) # E: No overload variant of "prod" matches argument type | ||
|
||
np.cumprod(a, axis=1.0) # E: Argument "axis" to "cumprod" has incompatible type | ||
np.cumprod(a, out=False) # E: Argument "out" to "cumprod" has incompatible type | ||
|
||
np.size(a, axis=1.0) # E: Argument "axis" to "size" has incompatible type | ||
|
||
np.around(a, decimals=1.0) # E: No overload variant of "around" matches argument type | ||
np.around(a, out=type) # E: No overload variant of "around" matches argument type | ||
|
||
np.mean(a, axis=1.0) # E: No overload variant of "mean" matches argument type | ||
np.mean(a, out=False) # E: No overload variant of "mean" matches argument type | ||
np.mean(a, keepdims=1.0) # E: No overload variant of "mean" matches argument type | ||
|
||
np.std(a, axis=1.0) # E: No overload variant of "std" matches argument type | ||
np.std(a, out=False) # E: No overload variant of "std" matches argument type | ||
np.std(a, ddof='test') # E: No overload variant of "std" matches argument type | ||
np.std(a, keepdims=1.0) # E: No overload variant of "std" matches argument type | ||
F42D td> | ||
np.var(a, axis=1.0) # E: No overload variant of "var" matches argument type | ||
np.var(a, out=False) # E: No overload variant of "var" matches argument type | ||
np.var(a, ddof='test') # E: No overload variant of "var" matches argument type | ||
np.var(a, keepdims=1.0) # E: No overload variant of "var" matches argument type |
Uh oh!
There was an error while loading. Please reload this page.