OWNDATA flag and reshape() -- views vs. copies

classic Classic list List threaded Threaded
2 messages Options
Reply | Threaded
Open this post in threaded view
|

OWNDATA flag and reshape() -- views vs. copies

Guillaume Desjardins
I'm pretty new to Python and numpy (longtime c / matlab programmer),
but after a read through some of the past threads and Travis' "Guide
to Numpy", I think I have a fairly good understanding of how the
reshape() function / methods work, with regards to views and copies.
For what its worth (and to make things clearer), my understanding is
that:

* Function reshape: create a view, or if it can't (i.e. resulting
array cannot be expressed with constant stride parameters), a copy
* Method obj.reshape(): creates a view, or throws an exception if it can't

Now assuming that is the case, I do not understand the behaviour of
the following code.

a = array([[1,2,3,4],[5,6,7,8],[9,10,11,12]]);
a.flags
 C_CONTIGUOUS : True
 F_CONTIGUOUS : False
 OWNDATA : True
 WRITEABLE : True
 ALIGNED : True
 UPDATEIFCOPY : False

b = a[1:,1:3] # creates view of a
>> array([[ 6,  7],
            [10, 11]])
b.flags
 C_CONTIGUOUS : False
 F_CONTIGUOUS : False
 OWNDATA : False
 WRITEABLE : True
 ALIGNED : True
 UPDATEIFCOPY : False

c = reshape(b,(4,1))  # RESHAPE FUNCTION: should copy, as view of this
is impossible (? isn't it ?)
c
>> array([[ 6],
        [ 7],
        [10],
        [11]])
c.flags
 C_CONTIGUOUS : True
 F_CONTIGUOUS : False
 OWNDATA : False
 WRITEABLE : True
 ALIGNED : True
 UPDATEIFCOPY : False

First question: if c is a copy of b, then why isn't the OWNDATA set to true ?
To prove that it is indeed a copy,
>> c[0] = 600
modifies the values of c but not of b and a (while modifying b - which
is clearly a view - also modifies a)

d = b.reshape((4,1))   # RESHAPE METHOD: same thing but with method...
shouldn't this give an error ?
d.flags
 C_CONTIGUOUS : True
 F_CONTIGUOUS : False
 OWNDATA : False
 WRITEABLE : True
 ALIGNED : True
 UPDATEIFCOPY : False

Second question: shouldn't b.reshape((4,1)) raise a ValueError since
it can't (as far as I see it) create a view ?
Once again, modifying d does not affect b or a (hence it is a copy).

Thanks for clearing up this issue. It is imperative that I know
exactly when numpy creates views vs. copies (and that I understand all
the intricacies), as I'm planning on doing A LOT of reshape() with
inplace modifications.

Hope I'm not polluting the mailing list with a newbie question.
Thanks in advance,

--
Guillaume

ps: sorry to the moderators for having submitted this twice (once as a
non-member, and after signing up)
_______________________________________________
Numpy-discussion mailing list
[hidden email]
http://projects.scipy.org/mailman/listinfo/numpy-discussion
Reply | Threaded
Open this post in threaded view
|

Re: OWNDATA flag and reshape() -- views vs. copies

Eric Firing
Guillaume Desjardins wrote:

> I'm pretty new to Python and numpy (longtime c / matlab programmer),
> but after a read through some of the past threads and Travis' "Guide
> to Numpy", I think I have a fairly good understanding of how the
> reshape() function / methods work, with regards to views and copies.
> For what its worth (and to make things clearer), my understanding is
> that:
>
> * Function reshape: create a view, or if it can't (i.e. resulting
> array cannot be expressed with constant stride parameters), a copy
> * Method obj.reshape(): creates a view, or throws an exception if it can't
>
> Now assuming that is the case, I do not understand the behaviour of
> the following code.
>
> a = array([[1,2,3,4],[5,6,7,8],[9,10,11,12]]);
> a.flags
>  C_CONTIGUOUS : True
>  F_CONTIGUOUS : False
>  OWNDATA : True
>  WRITEABLE : True
>  ALIGNED : True
>  UPDATEIFCOPY : False
>
> b = a[1:,1:3] # creates view of a
>>> array([[ 6,  7],
>             [10, 11]])
> b.flags
>  C_CONTIGUOUS : False
>  F_CONTIGUOUS : False
>  OWNDATA : False
>  WRITEABLE : True
>  ALIGNED : True
>  UPDATEIFCOPY : False
>
> c = reshape(b,(4,1))  # RESHAPE FUNCTION: should copy, as view of this
> is impossible (? isn't it ?)
> c
>>> array([[ 6],
>         [ 7],
>         [10],
>         [11]])
> c.flags
>  C_CONTIGUOUS : True
>  F_CONTIGUOUS : False
>  OWNDATA : False
>  WRITEABLE : True
>  ALIGNED : True
>  UPDATEIFCOPY : False
>
> First question: if c is a copy of b, then why isn't the OWNDATA set to true ?

It looks like creation of c is done in two steps: first a copy is made
of b, and then c is returned as a view of that copy.  I don't know if
this is intentional; it sees a bit odd.  I agree with you that I would
have expected c to own its data rather than refer to a base hidden in
the shadows.

In [62]:b.base
Out[62]:
array([[ 1,  2,  3,  4],
        [ 5,  6,  7,  8],
        [ 9, 10, 11, 12]])

In [63]:b
Out[63]:
array([[ 6,  7],
        [10, 11]])

In [64]:c.base
Out[64]:
array([[ 6,  7],
        [10, 11]])

In [65]:c
Out[65]:
array([[ 6],
        [ 7],
        [10],
        [11]])

Eric
_______________________________________________
Numpy-discussion mailing list
[hidden email]
http://projects.scipy.org/mailman/listinfo/numpy-discussion