Если x является списком, почему делает x + =, “ха” работают, в то время как x = x + “ха” выдает исключение?

Из того, что мало я знаю, + op для списков только требует, чтобы 2-й операнд был повторяем, который "ха" ясно является.

В коде:

>>> 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
задан Jonathan Leffler 22 August 2014 в 02:55
поделиться

3 ответа

Использование + = со списком похоже на вызов extend , а не + .

  • Вы можете вызвать extend с помощью итерации.
  • Вы можете использовать + только с другим списком.

Я могу только догадываться, почему было принято это решение, но полагаю, что это сделано из соображений производительности. Вызов + приводит к созданию нового объекта и копированию всех элементов, тогда как extend может использовать свободное пространство в существующем объекте списка, сохраняя копию в некоторых случаях.

Еще одним побочным эффектом этого решения является то, что если вы напишете x + = y , другие ссылки на список увидят изменение, но если вы используете x = x + y , тогда они не будут. Это показано ниже:

>>> 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']

Ссылки

Исходный код Python для списка .

Исходный код для + = :

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;
}

Исходный код для + :

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 ...
31
ответ дан 26 November 2019 в 20:41
поделиться

Вы думаете об этом задом наперед. Вы спрашиваете, почему x = x + 'ha' вызывает исключение, учитывая, что x + = 'ha' работает. На самом деле, вопрос в том, почему x + = 'ha' вообще работает.

Все согласны (я надеюсь), что 'abc' + 'ha' и [1, 2, 3] + ['h', 'a'] должны работать. И в этих случаях перегрузка + = для внесения изменений на месте кажется разумной.

Разработчики языка решили, что [1, 2, 3] + 'ha' не должны, потому что вы смешиваете разные типы. И это тоже кажется разумным.

Итак, вопрос в том, почему они решили разрешить смешивание различных типов в случае x + = 'ha' . В этом случае, я полагаю, есть пара причин:

  • Это удобное сокращение
  • Очевидно, что происходит (вы добавляете каждый из элементов в итерации к x )

В общем , Python пытается позволить вам делать то, что вы хотите, но там, где есть двусмысленность, он заставляет вас быть откровенным.

8
ответ дан 26 November 2019 в 20:41
поделиться

При определении операторов есть два разных оператора "add": Один называется __add__, другой __iadd__. Последний предназначен для in-place дополнений с +=, другой - обычный оператор +. http://docs.python.org/reference/datamodel.html содержит больше информации об этом.

5
ответ дан 26 November 2019 в 20:41
поделиться
Другие вопросы по тегам:

Похожие вопросы: