Why +=
works and +
doesn't work is "that's how its coded". But I haven't figured out any good reason for it. Lets focus simply on list addition
operator magic method list equiv
-------- ------------ ----------
+= (inplace add) __iadd__ list_inplace_concat
+ (add) __add__ list_concat
Inplace Add / list_inplace_concat works on any sequence. Under the covers, python simply calls list.extend
which turns the right hand side into an iterator and so works with all sequences
>>> test = []
>>> test += 'abc'
>>> test
['a', 'b', 'c']
Add / list_concat is hardcoded to work only with other lists. The underlying C code uses the internal data structure of the list to copy its elements.
>>> test + 'abc'
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: can only concatenate list (not "str") to list
Change the right hand side to a list and it works
>>> test + list('abc')
['a', 'b', 'c', 'a', 'b', 'c']
>>>
list_concat
is optimized to use the size of the two lists to know exactly how large the new list needs to be. Then it does member copy at the C structure level. What puzzles me is why there isn't a fallback when the "not a list" condition is detected. The list could be copied and extended.