-
-
Notifications
You must be signed in to change notification settings - Fork 32
Conversation
This isn't ready yet, but I wanted to get feedback about whether this was the right approach (lots of
I'm not sure what the alternative approaches are -- I thought about trying to create a special |
numpy/random/mtrand.pyi
Outdated
@overload | ||
def beta(self, a: float, b: float) -> float: ... | ||
@overload | ||
def beta(self, a: float, b: float, size: _Size) -> float: ... |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If size
is specified, you get an ndarray
, not a float.
numpy/random/mtrand.pyi
Outdated
@overload | ||
def beta(self, a: float, b: float, size: _Size) -> float: ... | ||
@overload | ||
def beta(self, a: ndarray, b: float) -> ndarray: ... |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unfortunately this isn't quite right -- if you pass in a zero-dimensional ndarray, you get a float back, not a ndarray:
In [17]: rs.beta(np.array(2), 2)
Out[17]: 0.3340049666412606
This sort of behavior (zero dimensional arrays -> scalars) is unfortunately quite common with NumPy.
EDIT: I see you already noted this in your comment :)
numpy/random/mtrand.pyi
Outdated
@overload | ||
def choice(self, a: int, *, | ||
replace: bool = ..., p: Optional[Sequence[float]] = ... | ||
) -> int: ... |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is np.int64
, not int
(at least not on Python 3)
numpy/random/mtrand.pyi
Outdated
@overload | ||
def choice(self, a: Sequence[_T], *, | ||
replace: bool = ..., p: Optional[Sequence[float]] = ... | ||
) -> _T: ... |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
a
gets cast to an ndarray, so the return value is the corresponding NumPy scalar type.
numpy/random/mtrand.pyi
Outdated
_T = TypeVar('_T') | ||
|
||
class RandomState: | ||
def __init__(self, state: Optional[Union[int, ndarray]] = ...) -> None: ... |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The constructor argument is called seed
, not state
:
https://docs.scipy.org/doc/numpy/reference/generated/numpy.random.RandomState.html
Also, it can accept sequences of integers ("array_like") not just ndarray instances.
numpy/random/mtrand.pyi
Outdated
@overload | ||
def beta(self, a: float, b: ndarray) -> ndarray: ... | ||
@overload | ||
def beta(self, a: ndarray, b: ndarray) -> ndarray: ... |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This method can also accept arbitrary "array-like" types which it coerces to ndarrays, e.g., lists of numbers.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hm... I'm not sure how to represent "array-like" types. A naive approach would be something like:
_ArrayLike = Union[Sequence[_T], ndarray]
But nested sequences are also _ArrayLike
and MyPy doesn't have support for recursive types (which we'd need for arbitrarily nested sequences).
There are going to be quite a few functions like these (e.g., all NumPy ufuncs), so it may make sense to incorporate some sort of template generation in the build process for this library. I guess ufuncs are objects, we so might be able to specify the type-casting rules once (for each number of function arguments) on the base class. But there are still lots of NumPy functions/methods that aren't ufuncs...
This is more concerning to me -- it basically blocks anyone from using our annotations with MyPy. I think we need to ensure that mypy can use our annotations without errors.
Yes, this sort of behavior is very unfortunate for us, and unfortunately is also quite prevalent in NumPy. My inclination is that our type-stubs should prioritize correctness more than catching all possible errors. Zero-dimensional arrays are somewhat usual to see in NumPy, but they do come up. Without typing support for array dimensionality, this would mean that many of these return values should be unsatisfying |
I believe I've figured out how to hack around the
Yeah, I think some template generation "build" makes a lot of sense. my approach w/ Jinja2 is pretty ugly (because of how it handles whitespace) and still fails
I'm willing to defer to your judgement here, but I'd personally lean the other way -- IME w/ MyPy is still limited enough that you almost never have "seamless" integration with any reasonably large codebase, and given that you have to adapt the coding style (to write "type-friendly" code) and do integration work anyways, I think it's reasonable to prioritize "correctness" (as long as the burden's not too much, like having to add some In any case, I think |
It conflicts with `@overload`s in type stubs
b38cc2b
to
813f0b9
Compare
Better overloading rules
@shoyer Sorry for the (very long) delay! I've pushed a new revision which (I believe) fully types out To avoid having to think too much about formatting, I also used https://github.com/ambv/black as a (manual) post-processing step of the generated stub files. I think the main unresolved questions I have are:
WDYT? |
The most significant benefit is changes to `@overload` around what counts as overlapping signatures that could unlock some functionality; see e.g. - numpy#44 (comment) - numpy#11 (comment)
The most significant benefit is changes to `@overload` around what counts as overlapping signatures that could unlock some functionality; see e.g. - #44 (comment) - #11 (comment)
Closing; but feel free to make a new PR against the NumPy main repo! |
No description provided.