What is the difference between i = i + 1 and i += 1 in a 'for' loop?

I found out a curious thing today and was wondering if somebody could shed some light into what the difference is here?

    import numpy as np

    A = np.arange(12).reshape(4,3)
    for a in A:
        a = a + 1

    B = np.arange(12).reshape(4,3)
    for b in B:
        b += 1

After running each for loop, A has not changed, but B has had one added to each element. I actually use the B version to write to a initialized NumPy array within a for loop.

The difference is that one modifies the data-structure itself (in-place operation) b += 1 while the other just reassigns the variable a = a + 1.

Just for completeness:

x += y is not always doing an in-place operation, there are (at least) three exceptions:

  • If x doesn't implement an __iadd__ method then the x += y statement is just a shorthand for x = x + y. This would be the case if x was something like an int.

  • If __iadd__ returns NotImplemented, Python falls back to x = x + y.

  • The __iadd__ method could theoretically be implemented to not work in place. It'd be really weird to do that, though.

As it happens your bs are numpy.ndarrays which implements __iadd__ and return itself so your second loop modifies the original array in-place.

You can read more on this in the Python documentation of "Emulating Numeric Types".

These [__i*__] methods are called to implement the augmented arithmetic assignments (+=, -=, *=, @=, /=, //=, %=, **=, <<=, >>=, &=, ^=, |=). These methods should attempt to do the operation in-place (modifying self) and return the result (which could be, but does not have to be, self). If a specific method is not defined, the augmented assignment falls back to the normal methods. For instance, if x is an instance of a class with an __iadd__() method, x += y is equivalent to x = x.__iadd__(y) . Otherwise, x.__add__(y) and y.__radd__(x) are considered, as with the evaluation of x + y. In certain situations, augmented assignment can result in unexpected errors (see Why does a_tuple[i] += ["item"] raise an exception when the addition works?), but this behavior is in fact part of the data model.

From: stackoverflow.com/q/41446833