Skip to content

Conversation

charris
Copy link
Member

@charris charris commented Oct 2, 2017

Update of #9571.

require a change in the total number of elements
The shape attribute is usually used to get at the current shape of an
array, but may also be used to reshape the array by assigning a different
tuple to it. As with `numpy.reshape`, one of the new shape dimensions can
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

'shape entries' or 'array dimensions' would be clearer

array, but may also be used to reshape the array by assigning a different
tuple to it. As with `numpy.reshape`, one of the new shape dimensions can
be -1, in which case its value is inferred from the length of the array and
remaining dimensions. This method of reshaping an array is not recommended,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The sentence ordering here might lead the reader to think that this sentence refers simply to the -1 behaviour.

tuple to it. As with `numpy.reshape`, one of the new shape dimensions can
be -1, in which case its value is inferred from the length of the array and
remaining dimensions. This method of reshaping an array is not recommended,
both because it can fail, and because it affects any code holding a
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is actually a feature I hadn't considered. For instance:

def reshape_view_only(x, shape):
    a = array(x. copy=False)
    a.shape = shape
    return a

May be used to "reshape" the array, as long as this would not
require a change in the total number of elements
The shape attribute is usually used to get at the current shape of an
array, but may also be used to reshape the array by assigning a different
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe add "in place" here?

@charris
Copy link
Member Author

charris commented Oct 3, 2017

Fixed.

array dimensions to it. As with `numpy.reshape`, one of the new shape
dimensions can be -1, in which case its value is inferred from the length
of the array and remaining dimensions. Reshaping an array in-place is not
recommended; not only may it fail, but it also affects any code holding a
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think elaborating on may it fail would be good, since I think that is the one reason to use it. Perhaps Unlike ndarray.reshape, this throws an exception if the reshape would require a copy.

@charris charris force-pushed the gh-9571 branch 4 times, most recently from 00582e8 to 9cfc01c Compare October 3, 2017 18:28
array dimensions to it. As with `numpy.reshape`, one of the new shape
dimensions can be -1, in which case its value is inferred from the length
of the array and remaining dimensions. Reshaping an array in-place will
fail if a copy is required, and it affects any code holding a reference to
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"affects any code holding a reference to the array in an indirect way" almost suggests that it affects views of the same array data, which is not the case.

So I'm not sure this part is helpful. It's really a statement about how creating new objects should be preferred to mutation (which I generally agree with), but this sort of general coding advice feels slightly out of place in a doc-string.

Copy link
Member Author

@charris charris Oct 3, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wanted to discourage using it for reshaping. Long ago I was tempted make a PR making ndarray.shape readonly, but backwards compatibility was a problem. Then again, I would rather ndarray.reshape raised an error if a copy was needed. Oh well ;)

Hmm. how come owndata if false here when a copy is made?

In [18]: ones((4,2))[::2].reshape(4).flags
Out[18]: 
  C_CONTIGUOUS : True
  F_CONTIGUOUS : True
  OWNDATA : False
  WRITEABLE : True
  ALIGNED : True
  UPDATEIFCOPY : False

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed the comment about the mutation.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Then again, I would rather ndarray.reshape raised an error if a copy was needed.

Exactly. This is one valid reason for mutating .shape. See #9818 for my proposal for adding a copy argument to reshape().

The shape property is usually used to get the current shape of an array,
but may also be used to reshape the array in-place by assigning a tuple of
array dimensions to it. As with `numpy.reshape`, one of the new shape
dimensions can be -1, in which case its value is inferred from the length
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: size of the array, not length

@@ -2949,6 +2951,11 @@ def luf(lamdaexpr, *args, **kwargs):
File "<stdin>", line 1, in <module>
ValueError: total size of new array must be unchanged
Copy link
Member

@eric-wieser eric-wieser Oct 4, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we add an example here for reshaping a non-contiguous array? Something a little less contrived than:

>>> np.eye(3)[:2,:2].shape = (-1,)
AttributeError: incompatible shape for a non-contiguous array

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With or without error?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With error. We already have an example of a without-error case. Should have said "non-contiguous array with an incompatible shape".

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All non-contiguos examples are a bit contrived. Here's another

>>> np.zeros((4,2))[::2].shape = (-1,)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: incompatible shape for a non-contiguous array

Changing the error message is a bit out of scope, but the current one seems OK to me, it is the (-1,) that is the incompatible shape.

@charris
Copy link
Member Author

charris commented Oct 4, 2017

Added example of failure.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants