From what little I know, + op for lists only requires the 2nd operand to be iterable, which “ha” clearly is.
In code:
>>> x = []
>>> x += "ha"
>>> x
['h', 'a']
>>> x = x + "ha"
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: can only concatenate list (not "str") to list
Using
+=with a list is like callingextend, not+.extendwith an iterable.+with another list.I can only guess why this decision was made, but I imagine it is for performance reasons. Calling
+results in a new object being created and all items being copied, whereasextendcan use free space in the existing list object saving a copy in some cases.Another side-effect of this decision is that if you write
x += yother references to the list will see the change but if you usex = x + ythen they will not. This is demonstrated below:References
Python source code for list.
Source code for
+=:static PyObject * list_inplace_concat(PyListObject *self, PyObject *other) { PyObject *result; result = listextend(self, other); if (result == NULL) return result; Py_DECREF(result); Py_INCREF(self); return (PyObject *)self; }Source code for
+:static PyObject * list_concat(PyListObject *a, PyObject *bb) { Py_ssize_t size; Py_ssize_t i; PyObject **src, **dest; PyListObject *np; if (!PyList_Check(bb)) { PyErr_Format(PyExc_TypeError, "can only concatenate list (not \"%.200s\") to list", bb->ob_type->tp_name); return NULL; } // etc ...