-
-
Notifications
You must be signed in to change notification settings - Fork 10.8k
ENH: Make ndarray.__array_finalize__ a callable no-op #20766
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
Conversation
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.
Great, thanks, looks all good to me. I suppose someone might find a way to fool fetching the attribute from the type, but I don't really see this plausible in practice (and it is generally the correct thing for a dunder).
I assume we won't backport this, so @BvB93 maybe you can finalize how this should look like with respect to the typing issues?
@seberg - what do you think regarding deprecating |
I am happy to deprecate it, but I it needs to go through a proper deprecation. Implementing |
Yes, I meant raising a |
Something like this should do the trick here: --- a/numpy/__init__.pyi
+++ b/numpy/__init__.pyi
@@ -1495,8 +1495,7 @@ def __array_function__(
- @property
- def __array_finalize__(self) -> None: ...
+ def __array_finalize__(self, obj: NDArray[Any], /) -> None: ... |
Note that |
This helps subclasses, who can now do super() in their own implementation.
In the process, __array_finalized__ is looked up on the subclass instead of the instance, which is more like python for methods like these. It cannot make a difference, since the instance is created in the same routine, so the instance method is guaranteed to be the same as that on the class.
7548232
to
485d45e
Compare
OK, I pushed the change, plus the deprecationwarning for |
485d45e
to
ecc7339
Compare
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.
Thanks for the followups, looks good. We probably should add a second release note for the deprecation as well to be complete. Could move the deprecation tests since we do that for almost all (but I don't care too much about it).
If you like, I can do those final touches.
numpy/core/src/multiarray/ctors.c
Outdated
"should be done is deprecated. Instead, just inherit from " | ||
"ndarray or, if that is not possible, explicitly set to " | ||
"ndarray.__array_function__; this will raise a TypeError " | ||
"in the future.") < 0) { |
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.
"in the future.") < 0) { | |
"in the future. (Deprecated since NumPy 1.23)") < 0) { |
numpy/core/tests/test_multiarray.py
Outdated
with pytest.warns(DeprecationWarning, | ||
match="__array_finalize__ = None"): | ||
a = np.array(1).view(NoFinalize) | ||
assert isinstance(a, NoFinalize) |
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.
Could move to test_deprecations
or add a test for when it is raised (the DeprecationTestCase always does this). But not super important, the ref-counting is obviously correct and that is the easiest error.
ecc7339
to
854dafa
Compare
@seberg - all makes sense. I pushed the changes (added to the deprecation commit, now the last one) |
Pushed a brief deprecation release note as well, planning on merging tomorrow, thanks. |
@seberg - I thought I had added a note myself, but I now see I forgot to add it (too used to |
Ah, was a bit surprised :). Anyway thanks for taking care of the deprecation as well! Lets put this in, if you are happy. |
Inspired by #20217, this gives
ndarray
a proper__array_finalize__
method (which does nothing) rather than just set it toNone
. This means the typing that was added can be consistent with the documentation for subclasses (the only place for which it is useful). It also means subclasses can safely dosuper().__array_finalize__(obj)
.One question is whether having
__array_finalize__ = None
should be deprecated (I doubt many subclasses would set that explicitly, but right now the code still checks).