codeforester
codeforester

Reputation: 43039

Assignment to an empty range?

I have this code:

import numpy as np
data = np.zeros((len(file_dirs),4097))
for i in range(len(file_dirs)):
    data[i][:] = np.loadtxt(file_dirs[i])

The loop seems to produce the same result with this as well:

for i in range(len(file_dirs)):
    data[i] = np.loadtxt(file_dirs[i])

What is the difference between data[i] and data[i][:] on the LHS?

Upvotes: 1

Views: 66

Answers (1)

juanpa.arrivillaga
juanpa.arrivillaga

Reputation: 96172

Slicing and indexing numpy.ndarray objects produces a view over the same underlying, primitive buffer. They are different Python objects sharing the same buffer. data[i] produces a new numpy.ndarray object, that is sliced with a full slice, which simply returns another object with a view over the same exact data, which was a view of the original. The item-assignment operator, container[item] = value, works in-place (as it does with built-in containers as well, like list and dict),

data[i][:] = np.loadtxt(file_dirs[i])

so that same buffer is modified. Hence, that acts equivalently to:

data[i] = np.loadtxt(file_dirs[i])

But note, this would not work the same way with Python list objects (and most other mutable objects you'll encounter in Python). A slice of a list produces a new object as well, but it is independent of the original without sharing memory.

>>> mylist = list(range(10))
>>> middle_six = mylist[2:-2]
>>> mylist
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> middle_six
[2, 3, 4, 5, 6, 7]
>>> middle_six[:] = [ -133, 212, 88,  23, 650,  -88]
>>> mylist
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> middle_six
[-133, 212, 88, 23, 650, -88]

And now note what happens with numpy arrays:

>>> import numpy as np
>>> arr = np.arange(10)
>>> middle_six = arr[2:-2]
>>> arr
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
>>> middle_six
array([2, 3, 4, 5, 6, 7])
>>> middle_six[:] = [98, 101, -88, 17, 525, 88]
>>> middle_six
array([ 98, 101, -88,  17, 525,  88])
>>> arr
array([  0,   1,  98, 101, -88,  17, 525,  88,   8,   9])

Note, only some operations in numpy produce a view. "Fancy indexing", for example, with a sequence of indices, does not produce a view:

>>> arr = np.arange(10)
>>> first_three = arr[[0,1,2]]
>>> arr
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
>>> first_three
array([0, 1, 2])
>>> first_three[:] = [42, 42, 42]
>>> arr
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
>>> first_three
array([42, 42, 42])
>>>

Upvotes: 2

Related Questions