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). Будь ласка, задайте нову або задайте подальші запитання в нитках коментарів під кожною відповіддю. Примітка: ваші зміни не втрачені, натисніть історію, і ви зможете скопіювати / вставити її в нове запитання.
Авель


здається, що це дає різні анси, але не так. Якщо ви хочете додати значення за допомогою оператора +, у вас є знак o []. c + = [c] дасть вам такий же результат, як і додавання.
Sharif Chowdhury

@SharifChowdhury Я вірю, що ви отримаєте такий самий результат
довірений

Відповіді:


142

Щоб пояснити "чому":

+Операція додає масив елементів у вихідному масиві. array.appendОперація вставляє масив (або будь-який об'єкт) в кінець вихідного масиву, який призводить до посиланням на себе в цьому місці (звідси і нескінченна рекурсія).

Різниця тут полягає в тому, що операція + діє специфічно, коли ви додаєте масив (він перевантажений, як і інші, див. Цей розділ щодо послідовностей) шляхом об'єднання елемента. Однак метод додавання робить буквально те, що ви запитуєте: додайте об'єкт з правого боку, який ви йому надаєте (масив або будь-який інший об'єкт), замість того, щоб брати його елементи.

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

Використовуйте, extend()якщо ви хочете використовувати функцію, яка діє аналогічно оператору + (як показали і інші). Не розумно робити навпаки: намагатися імітувати додавання разом із оператором + для списків (див. Моє попереднє посилання про те, чому).

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

Для розваги, невелика історія: народження модуля масиву в Python в лютому 1993 року. Це може вас здивувати, але масиви додавались після появи послідовностей та списків.


2
+1, оскільки я завжди підтримую точну інформацію. Посилання на офіційні документи - це завжди плюс!
ятанізм

10
Інша частина "чому": розумні люди очікують +бути симетричними: об'єднати список зі списком.
Бені Чернявський-Паскін

1
+1, Хороша точка Бені (хоча я міг би вважати це так само "розумним", щоб сказати, "об'єкт на rh стороні додається до масиву на lh стороні", але особисто я вважаю поточну поведінку більш розумною).
Авель

якщо елемент є одиночним рядком, наприклад, s = 'word', l = ['this', 'is']. Тоді l.append (s) та l + s мають бути однаковими. Я прав?
користувач3512680

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

1
+1: Чому мені не подобаються питання "чому": appendі +різні. Ось чому. Мені подобається ця відповідь, тому що пропозиції, що робити, мають більше сенсу.
С.Лотт

Чи не цей сайт відповідає на відповіді на поставлені запитання? Люди запитують, чому PHP називається PHP і чому __lt__його не можна перевантажувати в Python (сьогодні це може). Чому-питання є найважливішими, але найчастіше найскладніше відповісти: вони задають суть, а не вказівник на посібник. І звичайно: якщо ви не любите запитання (мені не подобається найбільше), тоді не відповідайте ;-)
Abel

Для подальшої демонстрації, можливо, шоу c += [c]і c.append(c[:])теж.
ефемієнт

2
@Abel: Чому так a+b != a*b? Вони різні операції. Ось відповідь. "Чому" не так корисний, як інші запитання, як-от "Як я можу правильно додавати файли?" Або "Що не так з цим додатком, що призводить до нескінченної рекурсії?" Запитання форми "Що мені робити з X" або "Що пішло не так, коли я зробив X"? Або "Що мені робити замість X" також допоможе комусь навчитися, але надасть цілеспрямовані, корисні та корисні відповіді.
С.Лотт

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.