If x is list, why does x += “ha” work, while x = x + “ha” throws an exception?

前端 未结 3 941
暖寄归人
暖寄归人 2021-01-31 14:35

From what little I know, + op for lists only requires the 2nd operand to be iterable, which \"ha\" clearly is.

In code:

>>> x = []
>>>          


        
3条回答
  •  灰色年华
    2021-01-31 14:57

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

    • You can call extend with an iterable.
    • You can only use + 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 ...
    

提交回复
热议问题