From what little I know, + op for lists only requires the 2nd operand to be iterable, which \"ha\" clearly is.
In code:
>>> x = []
>>>
Using += with a list is like calling extend, not +.
extend with 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, whereas extend can 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 += y other references to the list will see the change but if you use x = x + y then they will not. This is demonstrated below:
>>> x = ['a','b'] >>> y = ['c', d'] >>> z = x >>> x += y >>> z ['a', 'b', 'c', 'd'] >>> x = ['a','b'] >>> y = ['c', d'] >>> z = x >>> x = x + y >>> z ['a', 'b']
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 ...
When defining operators, there are two different "add" operators: One is called __add__, the other __iadd__. The latter one is for in-place additions with +=, the other one is the regular + operator. http://docs.python.org/reference/datamodel.html has more infos on that.
You're thinking about it backwards. You're asking why x = x + 'ha' throws an exception, given that x += 'ha' works. Really, the question is why x += 'ha' works at all.
Everyone agrees (I hope) that 'abc' + 'ha' and [1, 2, 3] + ['h', 'a'] should work. And in these cases, overloading += to do in-place modification seems reasonable.
The language designers decided that [1, 2, 3] + 'ha' shouldn't, because you're mixing different types. And that seems reasonable as well.
So the question is why they decided to allow mixing different types in the case of x += 'ha'. In this case, I imagine there are a couple reasons:
x)In general, Python tries to let you do what you want, but where there's ambiguity, it tends to force you to be explicit.