[Numpy-discussion] copy on demand

Chris Barker Chris.Barker at noaa.gov
Mon Jun 17 15:49:04 CDT 2002


Konrad Hinsen wrote:
 > Let's make this explicit. Given the following four expressions,
 
> 1) array
> 2) array[0]
> 3) array.view
> 4) array.view[0]


I thought I had I clear idea of what I wanted here, which was the
non-view stuff being the same as Python lists, but I discovered
something: Python lists provide slices that are copies, but they are
shallow copies, so nested lists, which are sort-of the equivalent of
multidimensional arrays, act a lot like the view behavior of NumPy
arrays:

make a "2-d" list
>>> l = [[i, 1+5] for i in range(5)]
>>> l
[[0, 6], [1, 6], [2, 6], [3, 6], [4, 6]]

make an array that is the same:
>>> a = array(l)
array([[0, 6],
       [1, 6],
       [2, 6],
       [3, 6],
       [4, 6]])

assign a new binding to the first element:
>>> b = a[0]
>>> m = l[0]

change something in it:
>>> b[0] = 30
>>> a
array([[30,  6],
       [ 1,  6],
       [ 2,  6],
       [ 3,  6],
       [ 4,  6]])


The first array is changed

Change something in the first element of the list:
>>> m[0] = 30
>>> l
[[30, 6], [1, 6], [2, 6], [3, 6], [4, 6]]

The first list is changed too.

Now try slices instead:
>>> b = a[2:4]

change an element in the slice:
>>>> b[1,0] = 55
>>> a
array([[30,  6],
       [ 1,  6],
       [ 2,  6],
       [55,  6],
       [ 4,  6]])>> a

The first array is changed

Now with the list
>>> m = l[2:4]
>>> m
[[2, 6], [3, 6]]
This is a copy, but it is a shallow copy, so:
>>> m[1][0] = 45

Change an element
>>> l
[[30, 6], [1, 6], [2, 6], [45, 6], [4, 6]]

The list is changed, but:
m[0] = [56,65]

>>> l
[[30, 6], [1, 6], [2, 6], [45, 6], [4, 6]]

The list doesn't change, where:

>>> b[0] = [56,65]
>>> a
array([[30,  6],
       [ 1,  6],
       [56, 65],
       [55,  6],
       [ 4,  6]])

The array does change

My conclusion is that nested lists and Arrays simply are different
beasts so we can't expect complete compatibility. I'm also wondering why
lists have that weird behavior of a single index returning a reference,
and a slice returning a copy. Perhaps it has something to so with the
auto-resizing of lists. That being said, I still like the idea of slices
producing copies, so:

> 1) array
An Array like we have now, but slice-is-copy
semantics.                                                                                                                                                                                               

> 2) array[0]
An Array of rank one less than array,  sharing data with array

> 3) array.view
An object that can do nothing but create other Arrays that share data
with array. I don't know if is possible but I'd be just as happy if
array.view returned None, and array.view[slice] returned an Array that
shared data with array. Perhaps there is some other notation that could
do this.

> 4) array.view[0]
Same as 2)

To add a few:

5) array[0:1] 
An Array with a copy of the data in array[0]

6) array.view[0:1] 
An Array sharing data with array

As I write this, I am starting to think that this is all a bit strange.
Even though lists treat slices and indexes differently, perhaps Arrays
should not. They really are different beasts. I also see why it was done
the way it was in the first place!

-Chris




-- 
Christopher Barker, Ph.D.
Oceanographer
                                    		
NOAA/OR&R/HAZMAT         (206) 526-6959   voice
7600 Sand Point Way NE   (206) 526-6329   fax
Seattle, WA  98115       (206) 526-6317   main reception

Chris.Barker at noaa.gov




More information about the Numpy-discussion mailing list