# [Numpy-discussion] Why ndarray provides four ways to flatten?

Nathaniel Smith njs at pobox.com
Tue Oct 28 21:23:23 EDT 2014

```On Wed, Oct 29, 2014 at 12:37 AM, Alexander Belopolsky <ndarray at mac.com> wrote:
>
> On Tue, Oct 28, 2014 at 1:42 PM, Stephan Hoyer <shoyer at gmail.com> wrote:
>>
>> .flat lets you iterate over all elements of a N-dimensional array as if it
>> was 1D, without ever needing to make a copy of the array. In contrast,
>> ravel() and reshape(-1) cannot always avoid a copy, because they need to
>> return another ndarray.
>
>
> In some cases ravel() returns a copy where a view can be easily constructed.
> For example,
>
>>>> x = np.arange(10)
>>>> y = x[::2]
>>>> y.ravel().flags['OWNDATA']
> True
>
> Interestingly, in the same case reshape(-1) returns a view:
>
>>>> y.reshape(-1).flags['OWNDATA']
> False
>
> (This suggests at least a documentation bug - numpy.ravel documentation says
> that it is equivalent to reshape(-1).)

Well, that's disturbing. Why have one implementation when you can have three...

> It is only in situations like this
>
>>>> a = np.arange(16).reshape((4,4))
>>>> a[1::2,1::2].ravel()
> array([ 5,  7, 13, 15])
>
> where flat view cannot be an ndarray, but .flat can still return something
> that is at least duck-typing compatible with ndarray (if not an ndarray
> subclass) and behaves as a view into original data.
>
> My preferred design would be for x.flat to return a flat view into x.  This
> would be consistent with the way .T and .real attributes are defined and
> close enough to .imag.

.flat cannot return a flat view analogous to .T, .real, .imag, because
those attributes return ndarray views, and .flat can't guarantee that.

OTOH trying to make .flat into a full duck-compatible ndarray-like
type is a non-starter; it would take a tremendous amount of work for
no clear gain.

Counter-proposal: document that .flat is only for iteration and should
be avoided otherwise, and add a copy = {True, False, "if-needed"}
kwarg to flatten/ravel/reshape. And the only difference between ravel
and flatten is the default value of this argument. (And while we're at
it, make it so that their implementation is literally to just call
.reshape.)

-n

--
Nathaniel J. Smith
Postdoctoral researcher - Informatics - University of Edinburgh
http://vorpus.org

```