how does numpy implement the slice

Viewed 32
import numpy as np

x = np.zeros((3, 3))

y = x[:, 0]

y[1] = 2 # x[1,0] is changed

print(x)

z = x[0, :]

z[2] = 3 # x[0, 2] is changed

print(x)

How does the data stored and implemented?

If c(or fortran) is used, 2-dim array x[3][3]

z=x[0,:], return a pointer point to the address of x[0][0], then z[2] = 3 can change the value of x[0][2].

But how does y[1]=2 do? The address of x[0][0] x[1][0] x[2][0] is not continuous.

Does numpy use another variable to remember the next element?

1 Answers
In [64]: x = np.zeros((3, 3))
In [65]: x
Out[65]: 
array([[0., 0., 0.],
       [0., 0., 0.],
       [0., 0., 0.]])

Some useful information about x:

In [66]: x.__array_interface__
Out[66]: 
{'data': (1510169114000, False),
 'strides': None,
 'descr': [('', '<f8')],
 'typestr': '<f8',
 'shape': (3, 3),
 'version': 3}

In [67]: x.strides
Out[67]: (24, 8)

'data' is some sort of pointer to the c array that stores the 9 values of x. It is accessed as 2d using the strides - step by 8 bytes to go from one column to the next, by 3*28 to go to the next row

y is view, an new array, but which shares memory with x:

In [68]: y = x[:, 0]    
In [69]: y
Out[69]: array([0., 0., 0.])

In [70]: y.__array_interface__
Out[70]: 
{'data': (1510169114000, False),         # same data as x
 'strides': (24,),                       # going down rows
 'descr': [('', '<f8')],
 'typestr': '<f8',
 'shape': (3,),
 'version': 3}

In [71]: y.base
Out[71]: 
array([[0., 0., 0.],
       [0., 0., 0.],
       [0., 0., 0.]])

Modifying a y element modifies the same one in x:

In [72]: y[1] = 2
In [73]: y
Out[73]: array([0., 2., 0.])

In [74]: x
Out[74]: 
array([[0., 0., 0.],
       [2., 0., 0.],
       [0., 0., 0.]])

A view of a row:

In [75]: z = x[0, :]    
In [76]: z
Out[76]: array([0., 0., 0.])

In [77]: z.__array_interface__
Out[77]: 
{'data': (1510169114000, False),
 'strides': None,
 'descr': [('', '<f8')],
 'typestr': '<f8',
 'shape': (3,),
 'version': 3}

In [78]: z.strides
Out[78]: (8,)           # same column stride

Modifying a z element changes y also (if the overlap):

In [79]: z[0]=3
In [80]: y
Out[80]: array([3., 2., 0.])

This striding also makes reshaping fast - no data copies. Also transpose is fast.

In [81]: xt = x.transpose()
In [82]: xt
Out[82]: 
array([[3., 2., 0.],
       [0., 0., 0.],
       [0., 0., 0.]])
In [83]: xt.strides
Out[83]: (8, 24)        # same base, just switched strides
Related