>>> a = ([0],) # a tuple (immutable) containing a list (mutable)
>>> a[0] = a[0] + [1]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'tuple' object does not support item assignment
>>> a
([0],)
>>> a[0] += [1]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'tuple' object does not support item assignment
>>> a
([0, 1],)
Though to be fair, technically nothing prevents "+" from mutating either operator (it'd just get you tarred and feathered).EDIT: Tried it myself. Sure enough, it throws the exception, but still adds the item. This seems like a bug.
EDIT Part 2: I understand now. `a[0] += [1]` is internally translated to `a[0] = a[0].__iadd__([1])`. The right-hand side is interpreted, mutating a[0] in-place as expected. But then the re-assignment happens, which throws the exception since you're trying to re-assign a value in a tuple, which is immutable.
If you are using a value type, `__iadd__`[1] can return a new value. So:
x = 5
y = x
x += 3
y is not x and y == 5
But if you're using a reference type, it is allowed to mutate the reference and return the original reference. x = [1, 2]
y = x
x += [3, 4]
y is x and y == [1, 2, 3, 4]
[1]: https://docs.python.org/3/reference/datamodel.html#object.__...edit: I might have misunderstood your question. If you meant "why it's not equivalent" please see the falkaer's answer.
Yes. For example for std::string `a = a + b;` will (at least notionally) create a temporary string and then use the assignment operator. `a += b;` will not do this.