1
import numpy as np                
a = np.arange(0,60,5)            
a = a.reshape(3,4)                                    

for x in np.nditer(a, op_flags = ['readwrite']):          
   x[...] = 2*x              
print 'Modified array is:'              
print a

In the above code, why can't we simply write x=2*x instead of x[...]=2*x?

ayhan
  • 70,170
  • 20
  • 182
  • 203
  • If you write `x = 2*x` inside that loop, you just create a new variable x (different from the one that comes from the iteration) and assign the result to it. With `x[...] = 2*x`, you are modifying x directly. You might want to check [this post](https://nedbatchelder.com/text/names.html). – ayhan Sep 02 '18 at 10:08
  • 2
    @user2285236: `x = 2*x` doesn't create a new variable. It's just that the variable isn't the thing we need to change. Assigning to the variable doesn't help us. – user2357112 Sep 02 '18 at 10:09
  • What was wrong with this question that somebody downvoted it? – Wojciech Kaczmarek Sep 02 '18 at 10:11
  • 1
    If you are a numpy beginner, don't spend much time on `nditer`. Focus on whole array operations, like `b=2*a`. Even when you must use iteration, it isn't the fastest or simplest. – hpaulj Sep 02 '18 at 13:01
  • The main `nditer` tutorial, https://docs.scipy.org/doc/numpy/reference/arrays.nditer.html, is most useful if you read all the way to the end, and experiment with the `cython` port. Otherwise you'll get a false sense of its usefulness. – hpaulj Sep 02 '18 at 17:14
  • See also https://stackoverflow.com/q/42190783 – hpaulj Sep 04 '18 at 01:23

1 Answers1

2

No matter what kind of object we were iterating over or how that object was implemented, it would be almost impossible for x = 2*x to do anything useful to that object. x = 2*x is an assignment to the variable x; even if the previous contents of the x variable were obtained by iterating over some object, a new assignment to x would not affect the object we're iterating over.

In this specific case, iterating over a NumPy array with np.nditer(a, op_flags = ['readwrite']), each iteration of the loop sets x to a zero-dimensional array that's a writeable view of a cell of a. x[...] = 2*x writes to the contents of the zero-dimensional array, rather than rebinding the x variable. Since the array is a view of a cell of a, this assignment writes to the corresponding cell of a.

This is very similar to the difference between l = [] and l[:] = [] with ordinary lists, where l[:] = [] will clear an existing list and l = [] will replace the list with a new, empty list without modifying the original. Lists don't support views or zero-dimensional lists, though.

user2357112
  • 260,549
  • 28
  • 431
  • 505
  • The fact that `x` is 0d, and requires `x[..,]` instead of `x[:]` is part of why `nditer` is unsuitable for numpy beginners. – hpaulj Sep 02 '18 at 13:07