-
-
Notifications
You must be signed in to change notification settings - Fork 10.8k
BUG,MAINT: Updateifcopy arrays should always be copied. #9249
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
Before this, one would have In [1]: a = np.ones(10)[::2] In [2]: a.writeable Out[2]: True In [3]: b = np.array(a.flat, copy=False) In [4]: a.writeable Out[4]: False because b held a reference to the updateifcopy array a.flat.__array__(), keeping it from being deallocated and resetting a to writeable. That was because the array constructor returned a.flat.__array__() directly instead of making a copy. It seems that in normal usage it would be better to return a copy in these cases and this commit makes that change. Closes numpy#9244.
So do I understand correctly that what this PR does is make it so that if the array passed into If so, why is this better than making I guess my general concern is that yeah, |
I don't think we can change that without breaking things. All this PR does is avoid the side affect of locking the array I note that This PR is not intended as a big fix, merely a small fix that should be mostly unnoticed. |
It seems hard to imagine someone actually using the updateifcopy here, but its true, the clean thing would be to somehow deprecate it first. It might be interesting to check if this (sometimes unnecessary?) copy is triggered within the numpy test suit (outside of a possibly odd |
That said, not having this is probably not a big deal. |
I don't know, I could be wrong, but my intuition is that there could totally be code doing a2 = np.asarray(a.flat)
a2[0] = ... And in fact I'd expect this to be the most common way to write code that (inadvertently) relies on the UPDATEIFCOPY of |
I think the more common use would be
Where it is clear that a is being modified. I have no statistics on how folks think |
Sure, but that doesn't go via |
Is there a strong argument for Perhaps something like this would also be useful: a = np.arange(2)[::2]
with np.contiguous_view(a) as a_contig:
a_contig[0] = 5 Implemented as @contextlib.contextmanager
def contiguous_view(a, order='C'):
if a.flags[order + '_CONTIGUOUS']:
yield a
else:
b = np.array(a, order=order, subok=True, copy=True)
try:
yield b
finally:
a[...] = b which does the update-if-copy behaviour, but using a predictable context manager. |
In general UPDATEIFCOPY gets used in a number of places internally, and not just when you need a contiguous "view" of a non-contiguous array. For example, it can be used to work around dtype mismatches between a ufunc loop and an |
There are seven places where updateifcopy arrays are created:
|
Just for giggles, I returned an ordinary copy instead of an updateifcopy array from the flat iterator, and all tests pass except the one that checks if it is updateifcopy 8-) |
I'm going to suggest that we change |
I note that the current |
👍
Not sure about this... it seems like it's useful to have a standard way to explicitly coerce to an ndarray when you want to? Like in dask you can do We might also want to consider deprecating |
Closing this and creating an issue instead. |
Before this, one would have
because b held a reference to the updateifcopy array a.flat.array(),
keeping it from being deallocated and resetting a to writeable. That was
because the array constructor returned a.flat.array() directly
instead of making a copy. It seems that in normal usage it would be
better to return a copy in these cases and this commit makes that
change.
Closes #9244.