Является ли поведение списка Python + = iterable документированным в любом месте?
Похоже, что в Python list += x
работает для любого итеративного x
:
In [6]: l = []
In [7]: l += [1]
In [8]: l += (2, 3)
In [9]: l += xrange(5)
In [10]: l
Out[10]: [1, 2, 3, 0, 1, 2, 3, 4]
Является ли это поведение документированным где угодно?
Чтобы контрастировать это с list + x
, последний работает только в том случае, если x
также является list
. Это описано в документации.
Ответы
Ответ 1
Из Гвидо ван Россум:
Он работает так же, как .extend()
, за исключением того, что он также возвращает self
. я не может найти документы, объясняющие это.: - (
Вот соответствующий исходный код, взятый из listobject.c
:
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;
}
Я собрал отчет об ошибке, чтобы зафиксировать документацию: http://bugs.python.org/issue16701
Ответ 2
Нет (Guido подтверждает, благодаря Ashwini Chaudhary). Поведение +=
для последовательностей в целом недоказано. Я пришел к выводу, что спецификацией не требуется, чтобы x + y
, где x
- список, а y
некоторая другая итерабельная ошибка (так что другие реализации могли ее разрешить), и что другие реализации могут ограничивать +=
для получения однородных операндов.
Однако причины не делать этого очевидны: python вообще пытается делать правильные вещи с операндами, вместо того, чтобы требовать жесткого равенства типов. Настоящая загадка заключается в том, почему гетерогенное добавление не разрешено списками.
Обновление: я никогда не думал о проблеме неоднородного сложения, в основном потому, что itertools.chain
является в значительной степени полным решением проблемы.
Комментарии от тех, кто больше знаком с внутренними компонентами Python, могут объяснить, почему добавление должно быть однородным. (Вопрос здесь: Почему добавление списка Python должно быть однородным?)
Ответ 3
Теперь теперь документировано в Python 3.4+ и Python 2.7:
4.6.3. Типы изменяемой последовательности
Операции в следующей таблице определены в изменяемых типах последовательностей. collections.abc.MutableSequence
ABC предоставляется, чтобы упростить правильное выполнение этих операций над пользовательскими типами последовательностей.
[Ниже] s
- это экземпляр типа изменяемой последовательности, t
- любой итерируемый объект, а x
- произвольный объект, который соответствует любым ограничениям типа и значения, налагаемым s
(например, bytearray
принимает только целые числа, которые соответствуют ограничению значения 0 <= x <= 255
).
s.extend(t)
или s += t
extends s
с содержимым t
(по большей части такое же, как s[len(s):len(s)] = t
)
Итак, теперь задокументировано, что для любого изменяемого типа последовательности s
, s += t
является синонимом s.extend(t)
.