If x is a list, then why does x + = "ha" work, and x = x + "ha" throws an exception?

From what I know, + op for lists requires the second operand to be iterable, that "ha" is clearly there.

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 
+46
operators python list
Jul 09 2018-10-09T00:
source share
3 answers

Using += with a list is like calling extend , not + .

  • You can invoke extend with iteration.
  • You can only use + with a different list.

I can only guess why this decision was made, but I think it is for performance reasons. Calling + leads to the creation of a new object and the copying of all elements, while extend can use the free space in an existing list object, saving a copy in some cases.

Another side effect of this solution is that if you write x += y , other links to the list will see this change, but if you use x = x + y , then they will not. This is shown 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 a 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 ...
+33
Jul 09 2018-10-10T00:
source share

You think about it back. You ask why x = x + 'ha' throws an exception, given that x += 'ha' works. In fact, 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 make the modification in place seems reasonable.

The language developers decided that [1, 2, 3] + 'ha' should not, because you are mixing different types. And that also seems reasonable.

Therefore, the question arises as to why they decided to allow mixing of different types in the case x += 'ha' . In this case, I think there are several reasons:

  • It is a comfortable haircut
  • Obviously what happens (you add each of the elements to iterable in x )

In general, Python is trying to let you do what you want, but where there is ambiguity, it seeks to make you be explicit.

+8
Jul. 09 '10 at 21:40
source share

When defining statements, there are two different add statements: one called __add__ , the other __iadd__ . The latter refers to complements in place with += , and the other is a regular + operator. http://docs.python.org/reference/datamodel.html contains more information about this.

+5
Jul 22 '10 at 9:13
source share



All Articles