[Numpy-discussion] Should arr.diagonal() return a copy or a view? (1.7 compatibility issue)

Nathaniel Smith njs at pobox.com
Fri May 11 11:42:35 EDT 2012


I've been trying to sort through the changes that landed in master
from the missingdata branch to figure out how to separate out changes
related to NA support from those that aren't, and noticed that one of
them should probably be flagged to the list. Traditionally,
arr.diagonal() and np.diagonal(arr) return a *copy* of the diagonal.
Now, they return a view onto the original array.

On the one hand, this seems like it's clearly the way it should have
been since the beginning -- I'd expect .diagonal() to be a cheap
operation, like .transpose() and .reshape(). But, it's a potential
compatibility break if there is code out there that assumes diagonal()
returns a copy and can be scribbled on without affecting the original
array:

# 1.6:
>>> a = np.ones((2, 2))
>>> d = a.diagonal()
>>> d[0] = 3
>>> a
array([[ 1.,  1.],
       [ 1.,  1.]])

# current master/1.7:
>>> a = np.ones((2, 2))
>>> d = a.diagonal()
>>> d[0] = 3
>>> a
array([[ 3.,  1.],
       [ 1.,  1.]])

This is dangerous, obviously, and tricky to handle, since there's no
clear way to detect it and give a DeprecationWarning.

One option might be to keep the new behavior, but mark the returned
view as not WRITEABLE, and then flip to WRITEABLE=True in 1.8. Going
from read-only to writeable would be a compatible change, so that way
we end up on the behaviour we want eventually (in 1.8), and have only
one backwards compatibility break (1.6 -> 1.7), but that break is
clean and obvious.

-- Nathaniel



More information about the NumPy-Discussion mailing list