Is i = i + n truly the same as i += n?

They don't have to be the same.

Using the + operator calls the method __add__ while using the += operator calls __iadd__. It is completely up to the object in question what happens when one of these methods is called.

If you use x += y but x does not provide an __iadd__ method (or the method returns NotImplemented), __add__ is used as a fallback, meaning that x = x + y happens.

In the case of lists, using l += iterable actually extends the list l with the elements of iterable. In your case, every character from the string (which is an iterable) is appended during the extend operation.

Demo 1: using __iadd__

>>> l = []
>>> l += 'table'
>>> l
['t', 'a', 'b', 'l', 'e']

Demo 2: using extend does the same

>>> l = []
>>> l.extend('table')
>>> l
['t', 'a', 'b', 'l', 'e']

Demo 3: adding a list and a string raises a TypeError.

>>> l = []
>>> l = l + 'table'
[...]
TypeError: can only concatenate list (not "str") to list

Not using += gives you the TypeError here because only __iadd__ implements the extending behavior.

Demo 4: common pitfall: += does not build a new list. We can confirm this by checking for equal object identities with the is operator.

>>> l = []
>>> l_ref = l # another name for l, no data is copied here
>>> l += [1, 2, 3] # uses __iadd__, mutates l in-place
>>> l is l_ref # confirm that l and l_ref are names for the same object
True
>>> l
[1, 2, 3]
>>> l_ref # mutations are seen across all names
[1, 2, 3]

However, the l = l + iterable syntax does build a new list.

>>> l = []
>>> l_ref = l # another name for l, no data is copied here
>>> l = l + [1, 2, 3] # uses __add__, builds new list and reassigns name l
>>> l is l_ref # confirm that l and l_ref are names for different objects
False
>>> l
[1, 2, 3]
>>> l_ref
[]

In some cases, this can produce subtle bugs, because += mutates the original list, while
l = l + iterable builds a new list and reassigns the name l.

BONUS

Ned Batchelder's challenge to find this in the docs


If in the second case, you wrap a list around n to avoid errors:

for n in l:
    i = i + [n]
print(i)

you get

['table']

So they are different operations.


No.

7.2.1. Augmented assignment statements:

An augmented assignment expression like x += 1 can be rewritten as x = x + 1 to achieve a similar, but not exactly equal effect. In the augmented version, x is only evaluated once. Also, when possible, the actual operation is performed in-place, meaning that rather than creating a new object and assigning that to the target, the old object is modified instead.