Python append () vs. оператор + в списках, почему они дают разные результаты?


113

Почему эти две операции ( append()соответственно +) дают разные результаты?

>>> c = [1, 2, 3]
>>> c
[1, 2, 3]
>>> c += c
>>> c
[1, 2, 3, 1, 2, 3]
>>> c = [1, 2, 3]
>>> c.append(c)
>>> c
[1, 2, 3, [...]]
>>> 

В последнем случае фактически существует бесконечная рекурсия. c[-1]и cтакие же. Чем отличается +операция?


1
при всем уважении к жизнеспособному новому вопросу: я откатился к исходному вопросу, чтобы сохранить его в чистоте (1 вопрос на поток, см. SO FAQ). Пожалуйста, задавайте новый или задавайте дополнительные вопросы в обсуждениях под каждым ответом. Примечание: ваши правки не теряются, щелкните историю, и вы можете скопировать / вставить ее в новый вопрос.
Abel


вроде бы дает разные ответы, но не так. Если вы хотите добавить значение с помощью оператора +, вы должны использовать знак []. c + = [c] даст тот же результат, что и append.
Шариф Чоудхури

@SharifChowdhury Я верю, что вы получите тот же результат
доверенный

Ответы:


144

Чтобы объяснить «почему»:

+Операция добавляет массив элементов в исходном массиве. array.appendОперация вставляет массив (или любой объект) в конец исходного массива, который приводит к ссылке на себя в этом месте (отсюда и бесконечная рекурсия).

Разница здесь в том, что операция + действует определенным образом, когда вы добавляете массив (он перегружен, как и другие, см. Эту главу о последовательностях), объединяя элемент. Однако метод append делает буквально то, о чем вы просите: добавляет объект с правой стороны, который вы ему даете (массив или любой другой объект), вместо того, чтобы брать его элементы.

Альтернатива

Используйте, extend()если вы хотите использовать функцию, которая действует аналогично оператору + (как здесь также показано другими). Было бы неразумно делать обратное: пытаться имитировать добавление с помощью оператора + для списков (см. Мою предыдущую ссылку о том, почему).

Маленькая история

Ради интереса, немного истории: рождение модуля массива в Python в феврале 1993 года. Это может вас удивить, но массивы были добавлены намного позже, чем появились последовательности и списки.


2
+1 потому что я всегда поддерживаю точную информацию. Ссылки на официальные документы - это всегда плюс!
jathanism 07

10
Другая часть «почему»: здравомыслящие люди ожидают +симметричности: объединить список со списком.
Бени Чернявский-Паскин

1
+1, Хорошая точка зрения, Бени (хотя я мог бы счесть «разумным» сказать «объект на правой стороне добавлен к массиву на левой стороне», но лично считаю текущее поведение более разумным).
Abel

если элемент состоит из одной строки, например s = 'word', l = ['this', 'is']. Тогда l.append (s) и l + s должны быть одинаковыми. Я прав?
user3512680

23

Оператор конкатенации +- это бинарный инфиксный оператор, который при применении к спискам возвращает новый список, содержащий все элементы каждого из двух его операндов. list.append()Метод является mutatorна listкоторый присоединяет свой единственный objectаргумент (в вашем конкретном примере списка c) к предмету list. В вашем примере это приводит к cдобавлению ссылки на себя (отсюда и бесконечная рекурсия).

Альтернатива конкатенации '+'

Этот list.extend()метод также является методом мутатора, который объединяет свой sequenceаргумент с субъектом list. В частности, он добавляет каждый из элементов sequenceв порядке итерации.

В сторону

Являясь оператором, +возвращает результат выражения в виде нового значения. Поскольку это mutatorметод без цепочки , он list.extend()изменяет список тем на месте и ничего не возвращает.

Массивы

Я добавил это из-за потенциальной путаницы, которую может вызвать приведенный выше ответ Абеля, смешав обсуждение списков, последовательностей и массивов. Arraysбыли добавлены в Python после последовательностей и списков, как более эффективный способ хранения массивов целых типов данных. Не путайте arraysс lists. Они не одинаковы.

Из документов массива :

Массивы являются последовательными типами и ведут себя очень похоже на списки, за исключением того, что тип хранимых в них объектов ограничен. Тип указывается во время создания объекта с помощью кода типа, который представляет собой один символ.


18

appendдобавляет элемент в список. если вы хотите расширить список новым списком, который вам нужно использовать extend.

>>> c = [1, 2, 3]
>>> c.extend(c)
>>> c
[1, 2, 3, 1, 2, 3]

4
Я подумал, что вполне понятно, почему результаты разные, ведь операции не совпадают! если бы это могло показаться +и extendдать другие результаты, нам было бы о чем подумать.
SilentGhost 07

1
+1: Почему мне не нравятся вопросы «почему»: appendи +разные. Поэтому. Мне нравится этот ответ, потому что он предлагает больше смысла в том, что делать.
S.Lott

Разве этот сайт не отвечает на заданные вопросы? Люди спрашивают, почему PHP называется PHP и почему __lt__его нельзя перегрузить в Python (в настоящее время это возможно). Вопросы «Почему» - самые важные, но зачастую на них сложнее всего ответить: они задают суть, а не указатель на руководство. И, конечно же: если вам не нравится вопрос (а мне не нравится больше всего), то не отвечайте ;-)
Abel

Для дальнейшей демонстрации, возможно, покажут c += [c]и c.append(c[:])тоже.
ephemient

2
@Abel: Почему a+b != a*b? Это разные операции. Это ответ. «Почему» не так полезен, как другие вопросы, например «Как правильно добавить?» Или «Что не так с этим дополнением, которое ведет к бесконечной рекурсии?» Вопросы формы «Что мне делать с X» или «Что пошло не так, когда я сделал X»? Или «Что мне делать вместо X» тоже поможет кому-то учиться, но даст целенаправленные, полезные и действенные ответы.
S.Lott

8

Списки Python неоднородны, поэтому элементы в одном списке могут быть объектами любого типа. Выражение: c.append(c)добавляет объект, cкаким бы он ни был, в список. В этом случае он сам делает список членом списка.

Выражение c += cскладывает два списка и присваивает результат переменной c. Перегруженный +оператор определяется в списках для создания нового списка, содержимым которого являются элементы в первом списке и элементы во втором списке.

Так что на самом деле это просто разные выражения, которые изначально используются для обозначения разных вещей.


7

Метод, который вы ищете extend(). Из документации Python :

list.append(x)
    Add an item to the end of the list; equivalent to a[len(a):] = [x].

list.extend(L)
    Extend the list by appending all the items in the given list; equivalent to a[len(a):] = L.

list.insert(i, x)
    Insert an item at a given position. The first argument is the index of the element before which to insert, so a.insert(0, x) inserts at the front of the list, and a.insert(len(a), x) is equivalent to a.append(x).


2

См. Документацию :

list.append (x)

  • Добавить элемент в конец списка; эквивалентно [len (a):] = [x].

list.extend (L) - Расширить список, добавив все элементы в данный список; эквивалентно [len (a):] = L.

c.append(c)"добавляет" c к себе как элемент . Поскольку список является ссылочным типом, это создает рекурсивную структуру данных.

c += cэквивалентно extend(c), которое добавляет элементы c к c.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.