Interesting point.
The reason it behaves like this is that
x[0]+=[2,3]
translates to
x[0] = x[0].__iadd__([2,3])
which means it first calls __iadd__
, which modifies the list in place, and only then attempts to perform the illegal assignment into the tuple.
(Of course, it's easy to workaround (e.g. @luispedro's answer), but I understand your question is not about how to workaround it.)
Is it a bug, feature or a PEP?
Hard to say. I tend to vote for "a bug", because of the Principle of Least Astonishment. One would expect x[0].extend(y)
to behave like a=x[0]; a.extend(y)
to behave like a=x[0]; a+=y
to behave like x[0]+=y
.
A possible fix (at least for python built-in types) can be to required that __setitem__(self, k, v)
should translate to no-op in case self[k] is v
. (and custom classes overriding __setitem__
should obey).