3

In Python >= 3.5:

x = np.zeros((2,3))
for x_e in x:
    x_e += 123

This operation returns a 2x3 matrix of all 123's. Whereas the following returns all zeros:

x = np.zeros((2,3))
for x_e in x:
    x_e = 123

This is a little off putting to me since x_e is an element from x and it doesn't totally feel like x is being updated.

Okay, I think this is a thing, and it is called 'in place' update? (similar to an in place algorithm?)

But, the jarring thing is this does not work with lists:

x = [0,0,0]
for x_e in x:
    x_e += 123

This returns the list

[0, 0, 0]

I would appreciate if someone can enlighten me on what precisely is happening here.

Dimitris Fasarakis Hilliard
  • 150,925
  • 31
  • 268
  • 253
Cem S.
  • 147
  • 2
  • 7
  • Possible dups : http://stackoverflow.com/questions/41446833/what-is-the-difference-between-i-i-1-and-i-1-in-a-for-loop, http://stackoverflow.com/questions/15376509/when-is-i-x-different-from-i-i-x-in-python – Divakar Mar 19 '17 at 18:39
  • @Divakar, Thanks for the pointers. But I believe they do not answer the third point about immutability of integers. Also, believe me that I couldn't find them when I was searching the internet for an answer. :) – Cem S. Mar 19 '17 at 18:56

2 Answers2

2

In the first snippet you perform an in-place addition on a ndarray object. Since each x_e is an ndarray the inplace operation succeeds and alters the elements.

In the second snippet you're just reassinging to the loop-variable. Nothing is performed on the elements of x.

In the third snippet you don't have a multidimentional list so each x_e is actually an int. Using += on an int doesn't change in-place, it returns a new integer object (which you don't store).

The following might be more related to the first:

x = [[0, 0, 0] for _ in range(3)]
for x_e in x:
    x_e += [123]

here each element of x is a list object [0, 0, 0] on which you add, in-place, the element 123. After executing, x will be:

[[0, 0, 0, 123], [0, 0, 0, 123], [0, 0, 0, 123]]
Dimitris Fasarakis Hilliard
  • 150,925
  • 31
  • 268
  • 253
1

Imagine you have that:

>>> x = np.array(range(5))
>>> x
array([0, 1, 2, 3, 4])

So now:

>>> x+123
array([123, 124, 125, 126, 127])

As you can see the '+' action is mapped to the array. So when you do create an array full of 0's and add 123 to the sub lists the array is consisted of is logical to have the above result.

coder
  • 12,832
  • 5
  • 39
  • 53
  • Yeah but, why doesn't the in place for loop operation work with lists? What is new to me is the in place operation in the for loop. I do understand the broadcasting as I am coming from Matlab. – Cem S. Mar 19 '17 at 18:39
  • @CemS. That's because you are changing a mutable object within `for` loop which is the sub-list of the main list and changing a mutable object, which is a reference to the original object and any change on it will affect the original object as well. – Mazdak Mar 19 '17 at 18:43
  • @CemS., yes in python lists and numpy arrays is not the same thing. For example another big difference a list has over an array is that built-in functions (like sum) are performed much faster in lists than arrays. We just use np.arrays for big data – coder Mar 19 '17 at 18:43
  • @coder In this case they are the same, this is only matter of mutability not their functionalities. – Mazdak Mar 19 '17 at 18:44
  • @Kasramvd, yes I agree I just wanted to clarify that the general case is that lists and numpy arrays are not always the same thing – coder Mar 19 '17 at 18:44