[Numpy-discussion] Ransom Proposals

Travis Oliphant oliphant.travis at ieee.org
Tue Mar 28 12:41:03 CST 2006

Tim Hochberg wrote:
> +1 Assuming I understand all of the implications.
> * When doing automated conversion from Numeric/numarray to numpy, 
> "reshape(obj) => asarray(obj).reshape()". Doing anything else is going 
> to cause breakage and/or massive slowdowns. Can the conversion tool 
> handle this? I would guess yes, but that's just a guess.
Why would we need to change this --- even to 
> * This means that "somenoncontiguousarray.reshape(newshape)" will 
> oftern raise an error. That's a good thing, but I figured I'd get it 
> out in the open now so no one is suprised.
I'm still not sold that raising an error here is a good thing, which is 
why I think the function should work as it always as and *not* be 
deprecated or hard to get at even if the method is changed to raise an 
error if the reshape cannot be accomplished without a copy.

Discontiguous arrays actually show up quite a bit.  I'm not convinced 
that Tim's concern over "confusion" between when something returns a 
view and when it returns a copy is that big of a deal.  I maintain it's 
only disconcerting for someone who wants to do something "advanced".  
That person will know how to figure it out.   If things are "fixed" then 
new users will get bitten by slow code or errors that don't make sense. 
  I'm opposed to making things unnecessarily hard for new users.

Let's discuss this with a particular example in mind that is not 
contrived to do 'in-place' operations.   I think this will exemplify the 
crux of the matter for those who may not quite understand what this 
discussion is about.

a = rand(4,5,3)
b = a.transpose().reshape(15,4)
c = a.reshape(15,4)

In this example b is now a copy of the data in a and c is a "view" of 
the data in a.   The reason for this is because a.transpose() returns a 
"view" of the data which is not C-style contiguous.   The reshape 
function needs to know how to go between a linear sequence of elements 
and a multidimensional array --- the default is current C-style 
contiguous (last-index varies the fastest). 

If I understand correctly, Tim want's the second line to raise an error 
so that the reshape method *always* returns a view.  I'm not enthused 
about having the second line raise an error because it is an example of 
common code (perhaps a transpose does not precede the reshape but a 
slice selection --- there are lots of ways to get discontiguous 
arrays).   As it stands, I think the only problems that arise are when 
the user wants to modify b and/or c in-place.  Then, one is not sure 
whether or not b (or c)  is pointing to the data of a or not.  

My argument is that the reshape method documentation should state that 
you should not modify the contents of the return value of reshape unless 
it doesn't matter whether or not you have a copy of the data.  I would 
even be willing to make 'views' un-writeable by default so that there 
was no way to "inadvertently" modify the data in a, unless you know you 
want to.

We had this discussion for ravel months ago and the flatten method which 
always returns copies was created.   The ravel method is another one 
that returns views when it can (contiguous) and copies when it can't. 

I think reshape and ravel are the only methods that behave this way.   
I'm not convinced that changing their current, standard behavior is 
going to buy us anything but more confusion.

> * Since x.reshape would no longer return copies, the order flag is 
> unnecessary.
I don't believe this.  See my other posts on the difference between the 
array striding and how you want to interpret the array.
> * numpy.reshape(obj, newshape) on the other hand, always copies, so it 
> *could* grow an order flag. I think that I'd prefer that it didn't; if 
> you need that kind of control of the resulting arrays you should be 
> using array to copy your matrices.
No, this is not what I understand.  the reshape function would not 
*always* copy but would behave as it currently does.  Again, you haven't 
sold me on the need to absolutely, all the time, return either views or 
copies.    I think such a dogmatic view is too limiting in this case.

I have not been bitten by this in over 10 years.  Why is this such an 
issue now?
> * What does fixing ravel to be consistent mean? Always return a view? 
> Or always return a copy? The latter seems more useful, as the first is 
> already covered by both obj.reshape(-1) and obj.flat.

I meant that whatever the behavior is for .reshape should be the same 
for .ravel since it is syntactic sugar for obj.reshape(-1)

And obj.flat is not even in the same ball-park since it returns an 
array_iterator object and not an array.



More information about the Numpy-discussion mailing list