In short: you cannot always rely on the ndarray.flags['OWNDATA']
.
>>> import numpy as np
>>> x = np.random.rand(2,2)
>>> y = x.T
>>> q = y.reshape(4)
>>> y[0,0]
0.86751629121019136
>>> y[0,0] = 1
>>> q
array([ 0.86751629, 0.87671107, 0.65239976, 0.41761267])
>>> x
array([[ 1. , 0.65239976],
[ 0.87671107, 0.41761267]])
>>> y
array([[ 1. , 0.87671107],
[ 0.65239976, 0.41761267]])
>>> y.flags['OWNDATA']
False
>>> x.flags['OWNDATA']
True
>>> q.flags['OWNDATA']
False
>>> np.may_share_memory(x,y)
True
>>> np.may_share_memory(x,q)
False
Because q
didn't reflect the change in the first element, like x
or y
, it must somehow be the owner of the data (somehow is explained below).
There is more discussion about the OWNDATA
flag over at the numpy-discussion mailinglist. In the How can I tell if NumPy creates a view or a copy? question, it is briefly mentioned that simply checking the flags.owndata
of an ndarray
sometimes seems to fail and that it seems unreliable, as you mention. That's because every ndarray
also has a base
attribute:
the base of an ndarray is a reference to another array if the memory originated elsewhere (otherwise, the base is None
). The operation y.reshape(4)
creates a copy, not a view, because the strides of y
are (8,16)
. To get it reshaped (C-contiguous) to (4,)
, the memory pointer would have to jump 0->16->8->24
, which is not doable with a single stride. Thus q.base
points to the memory location generated by the forced-copy-operation y.reshape
, which has the same shape as y
, but copied elements and thus has normal strides again: (16, 8)
. q.base
is thus not bound to by any other name as it was the result of the forced-copy operation y.reshape(4)
. Only now can the object q.base
be viewed in a (4,)
shape, because the strides allow this. q
is then indeed a view on q.base
.
For most people it would be confusing to see that q.flags.owndata
is False
, because, as shown above, it is not a view on y
. However, it is a view on a copy of y
. That copy, q.base
, is the owner of the data however. Thus the flags are actually correct, if you inspect closely.