1

I have a Numpy array and can successfully update all its elements with one line:

array_1 = np.array([1, 2, 3, 4])
array_1 = array_1 / 10.0

print(array_1)
# [0.1 0.2 0.3 0.4] -- Success!

However, when I have a list of Numpy arrays and iterate over them with a for in loop, I cannot apply the same operation and get back the desired results.

array_1 = np.array([1, 2, 3, 4])
array_2 = np.array([5, 6, 7, 8])
array_3 = np.array([9, 10, 11, 12])

print(array_1) # [1 2 3 4]
print(array_2) # [5 6 7 8]
print(array_3) # [ 9 10 11 12]

for array in [array_1, array_2, array_3]:
    array = array / 10.0

print(array_1) # [1 2 3 4] -- No changes??
print(array_2) # [5 6 7 8]
print(array_3) # [ 9 10 11 12]

Why am I unable to update these arrays inside a loop? My understanding is that in the line

for array in [array_1, array_2, array_3]:

array will be a pointer to each of the three Numpy arrays.

How can I fix this problem?

2
  • You have to distinguish "variable" from "value". In the first example you are creating a new value, and changing the binding of the variable array_1 to the new value. In the second example, you are creating a new value, and changing the binding of array - but array_1 still contains the old value. Commented Jul 16, 2021 at 21:44
  • Assigning to array makes it point to the new array, it doesn't update the array that it points to. Commented Jul 16, 2021 at 21:44

2 Answers 2

2

You can make a shallow copy of the target array inside the for loop to edit the original.

for array in [array_1,array_2,array_3]:
    array[:] = array / 10.0

EDIT With Explanation---

In the for loop the control variable is its own object that deep copies the item being iterated over. We can use the [:] operation to make a shallow copy of the target item that references the original object. The following code demonstrates this concept:

array_1 = ['foo']
print(id(array_1)) # Original object id
for array in [array_1]:
    array = [1]
    print(id(array)) # Deep copy id
for array in [array_1]:
    array[:] = [1]
    print(id(array)) # Original object id
Sign up to request clarification or add additional context in comments.

2 Comments

Can you please explain a bit more? Why do we need to use array[:] = ?
Yeah no problem, should've been clearer @stackoverflowuser2010
1

Becuse you're only assigning new values to the control variable of the loop, so you need to address the actual elements by indexing:

arrays = [array_1, array_2, array_3]

for i in range(len(arrays)):
    arrays[i] = arrays[i] / 10.0

or even more comprehensively:

arrays = [array / 10.0 for array in arrays]

or even by filtering:

arrays = list(filter(lambda x: x / 10.0, arrays))

EDIT:

As @ForceBru noted in the comments section, in-place division would force the return of a float type array whereas the original is int. So the following was changed in the first code snippet: arrays[i] /= 10.0 -> arrays[i] = arrays[i] / 10.0

6 Comments

This doesn't work for me. I get this error: TypeError: ufunc 'true_divide' output (typecode 'd') could not be coerced to provided output parameter (typecode 'l') according to the casting rule ''same_kind'' pointing to the arrays[i] /= 10.0 line. I'm using Python 3.7.
@stackoverflowuser2010, actually, I got the same error. Looks like the arrays are of integer type, but in-place division by a double (10.0) would require an array of type double, yet you can't write a double into an array of integers, hence the error. Division like np.array([9, 10, 11, 12]) / 10.0 works fine because it creates a new array.
@ForceBru: Is this a bug or a feature?
@stackoverflowuser2010, well, it didn't let you write a floating-point number into an array of integers - I guess that makes sense, since you didn't request any casting. However, NumPy 1.8 doesn't raise any errors in the same code and silently casts the resulting floats to integers. I think it's a feature that enforces better typing
@ForceBru: Hold on. Why does this work? arrays[0] = arrays[0] / 10.0. The LHS is an array of int, but the RHS is an array of double.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.