Яка різниця між методами списку Python додавати та розширювати?


3116

Яка різниця між методами списку append()та extend()?

Відповіді:


5248

append: Додає об’єкт в кінці.

x = [1, 2, 3]
x.append([4, 5])
print (x)

дає вам: [1, 2, 3, [4, 5]]


extend: Розширює список, додаючи елементи з ітерабельної програми.

x = [1, 2, 3]
x.extend([4, 5])
print (x)

дає вам: [1, 2, 3, 4, 5]


122
У чому різниця між extendта просто використанням оператора додавання - у наведеному вище прикладі x = x + [4, 5]?
Рохан

303
Насправді є велика різниця - x + [4, 5]дає вам новий список, призначений x - x.extend()вимкнення оригінального списку. Свою відповідь я докладу нижче.
Аарон Холл

@AaronHall @Rohan, але це те саме, що x += [4,5].
Astitva Srivastava

1
@AstitvaSrivastava Насправді, я думаю, що розширення швидше з точки зору байт-коду
MilkyWay90

1
Ключове слово при використанні append- « Об’єкт» . Якщо ви спробуєте скористатися extendі передати словник , він додасть ключ , а не весь хеш до кінця масиву.
Ентоні

640

appendдодає елемент до списку і extendоб'єднує перший список з іншим списком (або іншим ітерабельним, не обов'язково списком.)

>>> li = ['a', 'b', 'mpilgrim', 'z', 'example']
>>> li
['a', 'b', 'mpilgrim', 'z', 'example']

>>> li.append("new")
>>> li
['a', 'b', 'mpilgrim', 'z', 'example', 'new']

>>> li.append(["new", 2])
>>> li
['a', 'b', 'mpilgrim', 'z', 'example', 'new', ['new', 2]]

>>> li.insert(2, "new")
>>> li
['a', 'b', 'new', 'mpilgrim', 'z', 'example', 'new', ['new', 2]]

>>> li.extend(["two", "elements"])
>>> li
['a', 'b', 'new', 'mpilgrim', 'z', 'example', 'new', ['new', 2], 'two', 'elements']

489

Яка різниця між методами списку, що додаються та розширюються?

  • appendдодає свій аргумент як єдиний елемент до кінця списку. Довжина самого списку збільшиться на одиницю.
  • extendповторює аргумент, додаючи кожен елемент до списку, розширюючи список. Довжина списку збільшиться на скільки б елементів не було в ітерабельному аргументі.

append

list.appendМетод додає об'єкт в кінець списку.

my_list.append(object) 

Незалежно від об'єкта, будь-який номер, рядок, інший список чи щось інше, він додається в кінці my_listяк єдиний запис у списку.

>>> my_list
['foo', 'bar']
>>> my_list.append('baz')
>>> my_list
['foo', 'bar', 'baz']

Тому майте на увазі, що список є об’єктом. Якщо ви додасте інший список до списку, перший список буде одним об’єктом в кінці списку (який може бути не тим, що ви хочете):

>>> another_list = [1, 2, 3]
>>> my_list.append(another_list)
>>> my_list
['foo', 'bar', 'baz', [1, 2, 3]]
                     #^^^^^^^^^--- single item at the end of the list.

extend

list.extendМетод розширює список шляхом додавання елементів з ітератора:

my_list.extend(iterable)

Тож із розширенням кожен елемент ітерабельного файлу додається до списку. Наприклад:

>>> my_list
['foo', 'bar']
>>> another_list = [1, 2, 3]
>>> my_list.extend(another_list)
>>> my_list
['foo', 'bar', 1, 2, 3]

Майте на увазі, що рядок є ітерабельним, тому, якщо ви розширите список за допомогою рядка, ви додасте кожен символ під час повторення рядка (який може бути не тим, що вам потрібно):

>>> my_list.extend('baz')
>>> my_list
['foo', 'bar', 1, 2, 3, 'b', 'a', 'z']

Перевантаження оператора, __add__( +) та __iadd__( +=)

І оператори, +і +=оператори визначені для list. Вони семантично схожі на розширення.

my_list + another_list створює третій список в пам'яті, тож ви можете повернути його результат, але для цього потрібно, щоб другим ітерабельним був список.

my_list += another_listмодифікує список на місці (він є оператором на місці, і списки змінювані об'єкти, як ми вже бачили) , тому він не створює новий список. Він також працює як розширення, оскільки другий ітерабельний може бути будь-яким видом ітерабельного.

Не плутайтесь - my_list = my_list + another_listце не рівнозначно +=- це дає вам абсолютно новий список, призначений моєму списку.

Часова складність

Додаток має постійну часову складність , O (1).

Extend має часову складність, O (k).

Ітерація через декілька викликів appendдодає складності, роблячи її еквівалентною розширенні, а оскільки ітерація розширення реалізована в C, це завжди буде швидше, якщо ви збираєтесь додавати наступні елементи з ітерабельного до списку.

Продуктивність

Ви можете задатися питанням, що є більш ефективним, оскільки додаток можна використовувати для досягнення того ж результату, що і розширення. Наступні функції роблять те саме:

def append(alist, iterable):
    for item in iterable:
        alist.append(item)

def extend(alist, iterable):
    alist.extend(iterable)

Тож давайте час на них:

import timeit

>>> min(timeit.repeat(lambda: append([], "abcdefghijklmnopqrstuvwxyz")))
2.867846965789795
>>> min(timeit.repeat(lambda: extend([], "abcdefghijklmnopqrstuvwxyz")))
0.8060121536254883

Звернення до коментаря щодо часу

Коментатор сказав:

Ідеальна відповідь, я просто сумую за часом порівняння додавання лише одного елемента

Зробіть семантично правильну річ. Якщо ви хочете додати всі елементи в ітерабелі, скористайтесяextend . Якщо ви просто додаєте один елемент, використовуйте append.

Гаразд, давайте створимо експеримент, щоб побачити, як це працює в часі:

def append_one(a_list, element):
    a_list.append(element)

def extend_one(a_list, element):
    """creating a new list is semantically the most direct
    way to create an iterable to give to extend"""
    a_list.extend([element])

import timeit

І ми бачимо, що вихід з нашого способу створення ітерабельного просто використання розширення - це (незначна) трата часу:

>>> min(timeit.repeat(lambda: append_one([], 0)))
0.2082819009956438
>>> min(timeit.repeat(lambda: extend_one([], 0)))
0.2397019260097295

З цього ми дізнаємось, що від використання нічого, extendколи ми маємо лише одне , нічого не отримуємо елемент для додавання.

Крім того, ці таймінги не такі важливі. Я просто показую їм, щоб підкреслити, що в Python, якщо робити семантично правильну річ, це робить все правильно шляхом ™.

Можливо, ви можете протестувати таймінги на двох порівняних операціях і отримати неоднозначний або зворотний результат. Просто зосередьтеся на тому, щоб робити семантично правильну річ.

Висновок

Ми бачимо , що extendсемантичний ясніше, і що він може працювати набагато швидше , ніж append, якщо ви збираєтеся додати кожен елемент ітератора в список.

Якщо у вас є лише один елемент (не в ітерабелі) для додавання до списку, використовуйте append.


1
@Aaron Hall Один невеликий коментар в алгоритмі визначення часу. "extension_one" може повернути "злегка неправильний" час, оскільки також створюється список. Напевно, краще створити елементи у вигляді змінних ( ex1 = 0і ex2 = [0]) та передати ці змінні, якщо ви хочете бути більш суворими.
ilias iliadis

19
Ідеальна відповідь дійсно. А як щодо продуктивності l1 += l2vs l1.extend(l2)?
Жан-Франсуа Т.

6
@ Jean-FrancoisT .: l1 += l2і в l1.extend(l2)кінцевому підсумку виконати той самий код ( list_extendфункція в listobject.c). Єдині відмінності: 1. +=перепризначення l1(собі для lists, але перепризначення підтримує непорушні типи, які не є тим самим об'єктом після), що робить його незаконним, якщо l1насправді є атрибутом незмінного об'єкта; наприклад, t = ([],), t[0] += lstзазнає невдачі, в той час як t[0].extend(lst)буде працювати. 2. l1 += l2використовує виділені байт-коди, тоді як l1.extend(l2)використовує узагальнений метод відправки; це робить +=швидше, ніжextend .
ShadowRanger

3
Те, що +=необхідно перепризначити l1, означає, що в деяких випадках повільне відправлення extendчастково або повністю складається, не відводячись назад на ліву сторону. Наприклад, якщо listатрибут об'єкта self.l1 += l2і self.l1.extend(l2)має однакову продуктивність на моїй установці Python 3.6, просто тому, що реальна операція більше схожа self.l1 = self.l1.__iadd__(l2), а значить, вона повинна виконувати помірно дорого, STORE_ATTRщо self.l1.extend(l2)не потрібно.
ShadowRanger

2
Просте порівняння в локальних тестах: Для локальної змінної (так +=це просто використання STORE_FAST, що дуже дешево), де додане значення є існуючим listз одним елементом в ньому, при цьому операція повторюється 1000 разів, в середньому +=займала близько 33 нс , тоді як extendвзяли 78 нс, різниця 45 нс. Якщо l1глобальна (вимагає дорожчих STORE_GLOBAL), різниця звужується до 17 нс. Якщо l1це насправді local.l1(вимагає ще дорожчого STORE_ATTR), то між +=і extend(терміни приблизно однакові; extendчасом виграє) немає суттєвої різниці .
ShadowRanger

121

append додає один елемент. extendдодає список елементів.

Зауважте, що якщо ви передаєте список для додавання, він все одно додає один елемент:

>>> a = [1, 2, 3]
>>> a.append([4, 5, 6])
>>> a
[1, 2, 3, [4, 5, 6]]

62

Додавання проти розширення

введіть тут опис зображення

За допомогою додавання ви можете додати один елемент, який розширить список:

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

Якщо ви хочете розширити більше одного елемента, вам слід скористатися розширенням, оскільки ви можете додати лише один елемент або один список елементів:

>>> a.append([4,5])
>>> a
>>> [1,2,3,[4,5]]

Так що ви отримаєте вкладений список

Замість розширення ви можете розширити такий елемент, як цей

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

Або, інакше, від додавання, подовжуйте більше елементів за один раз, не вкладаючи список у оригінальний (це і є причиною розширення назви)

>>> a.extend([4,5,6])
>>> a
[1,2,3,4,5,6]

Додавання одного елемента обома методами

введіть тут опис зображення

І додавання, і розширення можуть додати один елемент до кінця списку, хоча додавання простіше.

додайте 1 елемент

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

розширити один елемент

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

Додавання ще елементів ... з різними результатами

Якщо ви використовуєте додавання для більш ніж одного елемента, вам доведеться передати список елементів як аргументів, і ви отримаєте НЕСТЕДОВАНИЙ список!

>>> x = [1,2]
>>> x.append([3,4])
>>> x
[1,2,[3,4]]

З розширенням натомість ви передаєте список як аргумент, але ви отримаєте список з новим елементом, який не вкладений у старий.

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

Таким чином, з більшою кількістю елементів, ви будете використовувати розширення, щоб отримати список з більшою кількістю елементів. Однак додавання списку не додасть до списку більше елементів, а один елемент, який є вкладеним списком, як ви чітко бачите у висновку коду.

введіть тут опис зображення

введіть тут опис зображення


61

Наступні два фрагменти семантично еквівалентні:

for item in iterator:
    a_list.append(item)

і

a_list.extend(iterator)

Останнє може бути швидшим, оскільки цикл реалізований у C.


20
Розширення ~ на 4 рази швидше на моїй машині, ніж додавання в циклі (16us vs 4us на 100 циклів нулів)
Alex L

6
extend()ймовірно, попередньо розміщується, хоча append()ймовірно, ні.
Божевільний фізик

@MadPhysicist: Для повноти, бувають випадки, коли extend() не можна чітко передбачити розміщення, оскільки деякі ітерабелі не реалізуються __len__(), але, як і ви, я здивуюсь, якщо вона не спробує. Деякий приріст продуктивності також пов'язаний з виконанням ітераційної частини в чистому С, а не в Python, як зазначено у відповіді Аарона .
Soren Bjornstad

44

append()Метод додає один елемент в кінець списку.

x = [1, 2, 3]
x.append([4, 5])
x.append('abc')
print(x)
# gives you
[1, 2, 3, [4, 5], 'abc']

extend()Метод приймає один аргумент, список, і додає кожен з елементів аргументу до первісного списку. (Списки реалізовані у вигляді класів. "Створення" списку справді створює клас. У списку є методи, які працюють над ним.)

x = [1, 2, 3]
x.extend([4, 5])
x.extend('abc')
print(x)
# gives you
[1, 2, 3, 4, 5, 'a', 'b', 'c']

З занурення в пітон .


Ви не можете розширити лише 6, оскільки це не під силу. І другий висновок у вашому прикладі неправильний. 'abc' додається як один елемент, оскільки ви передали його у extendсписок як один елемент ['abc']: [1, 2, 3, 4, 5, 'abc']. Для того, щоб ваш приклад виведення правильно, змініть Абетки рядок: x.extend('abc'). І видаліть x.extend(6)або змініть його на x.extend([6]).
анероїд

37

Ви можете використовувати "+" для повернення розширення, а не продовження на місці.

l1=range(10)

l1+[11]

[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 11]

l2=range(10,1,-1)

l1+l2

[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 9, 8, 7, 6, 5, 4, 3, 2]

Аналогічно +=для поведінки на місці, але з незначними відмінностями від append& extend. Одне з найбільших відмінностей +=від appendта extend, коли воно використовується у сферах функцій, дивіться у цій публікації в блозі .


Чи впливає використання "+" для повернення розширення чи впливає на часову складність?
франклін

5
@franklin см ця відповідь подробиці: stackoverflow.com/a/28119966/2230844
denfromufa

1
Я не бачу, як це відповідає на питання
pppery

22

append(object) - Оновлення списку, додаючи об’єкт до списку.

x = [20]
# List passed to the append(object) method is treated as a single object.
x.append([21, 22, 23])
# Hence the resultant list length will be 2
print(x)
--> [20, [21, 22, 23]]

extend(list) - По суті об'єднує два списки.

x = [20]
# The parameter passed to extend(list) method is treated as a list.
# Eventually it is two lists being concatenated.
x.extend([21, 22, 23])
# Here the resultant list's length is 4
print(x)
[20, 21, 22, 23]

20

extend()може використовуватися з аргументом ітератора. Ось приклад. Ви бажаєте зробити такий список зі списку списків таким чином:

З

list2d = [[1,2,3],[4,5,6], [7], [8,9]]

ти хочеш

>>>
[1, 2, 3, 4, 5, 6, 7, 8, 9]

Ви можете використовувати itertools.chain.from_iterable()для цього. Вихід цього методу є ітератором. Її реалізація рівнозначна

def from_iterable(iterables):
    # chain.from_iterable(['ABC', 'DEF']) --> A B C D E F
    for it in iterables:
        for element in it:
            yield element

Повернувшись до нашого прикладу, ми можемо це зробити

import itertools
list2d = [[1,2,3],[4,5,6], [7], [8,9]]
merged = list(itertools.chain.from_iterable(list2d))

і отримати список розшуку.

Ось як extend()можна рівномірно використовувати аргумент ітератора:

merged = []
merged.extend(itertools.chain.from_iterable(list2d))
print(merged)
>>>
[1, 2, 3, 4, 5, 6, 7, 8, 9]

2
Ця відповідь не суперечить
додатку

19

Це еквівалент оператора appendта його extendвикористання +:

>>> x = [1,2,3]
>>> x
[1, 2, 3]
>>> x = x + [4,5,6] # Extend
>>> x
[1, 2, 3, 4, 5, 6]
>>> x = x + [[7,8]] # Append
>>> x
[1, 2, 3, 4, 5, 6, [7, 8]]

Чому б не = + ?! Більш лаконічний
denfromufa

16

append () : В основному використовується в Python для додавання одного елемента.

Приклад 1:

>> a = [1, 2, 3, 4]
>> a.append(5)
>> print(a)
>> a = [1, 2, 3, 4, 5]

Приклад 2:

>> a = [1, 2, 3, 4]
>> a.append([5, 6])
>> print(a)
>> a = [1, 2, 3, 4, [5, 6]]

extension () : де extension () використовується для об'єднання двох списків або вставки декількох елементів в один список.

Приклад 1:

>> a = [1, 2, 3, 4]
>> b = [5, 6, 7, 8]
>> a.extend(b)
>> print(a)
>> a = [1, 2, 3, 4, 5, 6, 7, 8]

Приклад 2:

>> a = [1, 2, 3, 4]
>> a.extend([5, 6])
>> print(a)
>> a = [1, 2, 3, 4, 5, 6]

12

Цікавий момент, натякнутий, але не пояснений, полягає в тому, що розширення швидше, ніж додавання. Для будь-якого циклу, який додається всередині, слід вважати, що він замінений list.extend (обработаны_элементы).

Майте на увазі, що додавання нових елементів може призвести до перенаправлення всього списку до кращого місця в пам'яті. Якщо це робиться кілька разів, оскільки ми додаємо одночасно один елемент, загальна продуктивність страждає. У цьому сенсі list.extend є аналогом "" .join (рядок).


12

Додавання додає всі дані відразу. Ці дані будуть додані до новоствореного індексу. З іншого боку, extendяк випливає з назви, розширює поточний масив.

Наприклад

list1 = [123, 456, 678]
list2 = [111, 222]

З appendнами ми отримуємо:

result = [123, 456, 678, [111, 222]]

Поки extendми отримуємо:

result = [123, 456, 678, 111, 222]

8

Англійський словник визначає слова appendі extendяк:

додавати : додати (щось) до кінця письмового документа.
розширити : зробити більшим. Збільшити або розширити


З цим знанням тепер давайте розберемося

1) Різниця між appendіextend

append:

  • Додає будь-який об’єкт Python як-є до кінця списку (тобто як останній елемент у списку).
  • Отриманий список може бути вкладений і містити неоднорідні елементи (тобто список, рядок, кортеж, словник, набір тощо)

extend:

  • Приймає будь-який ітерабельний аргумент і збільшує список .
  • Отриманий список завжди є одновимірним списком (тобто не вкладається), і він може містити в ньому неоднорідні елементи (наприклад, символи, цілі числа, поплавок) в результаті застосування list(iterable).

2) Схожість між appendіextend

  • Обидва беруть рівно один аргумент.
  • Обидва змінюють список на місці .
  • В результаті обидва повертаються None.

Приклад

lis = [1, 2, 3]

# 'extend' is equivalent to this
lis = lis + list(iterable)

# 'append' simply appends its argument as the last element to the list
# as long as the argument is a valid Python object
list.append(object)

5

Я сподіваюся, що зможу зробити корисне доповнення до цього питання. Якщо у вашому списку зберігається об’єкт конкретного типу, наприклад Info, ось така ситуація extendне підходить. У forциклі та генеруванні Infoоб'єкта кожного разу, використовуючи extendдля зберігання його у своєму списку, він не вдасться. Виняток, як показано нижче:

TypeError: Об'єкт "Інформація" не може бути ітерабельним

Але якщо ви використовуєте appendметод, результат добре. Оскільки кожного разу, використовуючи extendметод, він завжди буде трактувати його як список або будь-який інший тип колекції, повторювати його та розміщувати після попереднього списку. Конкретний об'єкт очевидно не можна перебрати.


4

Відрізнити їх інтуїтивно

l1 = ['a', 'b', 'c']
l2 = ['d', 'e', 'f']
l1.append(l2)
l1
['a', 'b', 'c', ['d', 'e', 'f']]

Це як би l1відтворити тіло всередині її тіла (вкладене).

# Reset l1 = ['a', 'b', 'c']
l1.extend(l2)
l1
['a', 'b', 'c', 'd', 'e', 'f']

Це так, що два відокремлених особи одружуються і створюють єдину сім'ю.

Крім того, я складаю вичерпну схему всіх методів списку для вашої довідки.

list_methods = {'Add': {'extend', 'append', 'insert'},
                'Remove': {'pop', 'remove', 'clear'}
                'Sort': {'reverse', 'sort'},
                'Search': {'count', 'index'},
                'Copy': {'copy'},
                }

2

extend(L)розширює список, додаючи всі елементи в даному списку L.

>>> a
[1, 2, 3]
a.extend([4])  #is eqivalent of a[len(a):] = [4]
>>> a
[1, 2, 3, 4]
a = [1, 2, 3]
>>> a
[1, 2, 3]
>>> a[len(a):] = [4]
>>> a
[1, 2, 3, 4]

0

append"розширює" список (на місці) лише одним елементом , один об'єкт передається (як аргумент).

extend"розширює" список (на місці) на стільки елементів, скільки містить об'єкт, переданий (як аргумент).

Це може бути дещо заплутано для strоб'єктів.

  1. Якщо ви передаєте рядок як аргумент: appendдодасте один елемент рядка в кінці, але extendдодасть стільки "одиночних" 'str' елементів, скільки довжина цього рядка.
  2. Якщо ви передаєте список рядків як аргумент: appendвсе одно додасте один елемент "список" в кінці та extendдодасть стільки елементів "список", скільки довжина переданого списку.
def append_o(a_list, element):
    a_list.append(element)
    print('append:', end = ' ')
    for item in a_list:
        print(item, end = ',')
    print()

def extend_o(a_list, element):
    a_list.extend(element)
    print('extend:', end = ' ')
    for item in a_list:
        print(item, end = ',')
    print()
append_o(['ab'],'cd')

extend_o(['ab'],'cd')
append_o(['ab'],['cd', 'ef'])
extend_o(['ab'],['cd', 'ef'])
append_o(['ab'],['cd'])
extend_o(['ab'],['cd'])

виробляє:

append: ab,cd,
extend: ab,c,d,
append: ab,['cd', 'ef'],
extend: ab,cd,ef,
append: ab,['cd'],
extend: ab,cd,

0

Додавання та розширення є одним із механізмів розтягування в python.

Додавання: додає елемент до кінця списку.

my_list = [1,2,3,4]

Щоб додати новий елемент до списку, ми можемо використовувати метод додавання наступним чином.

my_list.append(5)

Місце за замовчуванням, який буде доданий новий елемент, завжди знаходиться в (довжина + 1) положення.

Вставка: метод вставки використовувався для подолання обмежень додавання. За допомогою вставки ми можемо чітко визначити точну позицію, в яку хочемо вставити наш новий елемент.

Дескриптор методу вставки (індекс, об'єкт). Потрібно два аргументи: перший індекс, який ми хочемо вставити наш елемент, а другий сам елемент.

Example: my_list = [1,2,3,4]
my_list[4, 'a']
my_list
[1,2,3,4,'a']

Розширити: Це дуже корисно, коли ми хочемо об'єднати два чи більше списків у єдиний список. Якщо ми хочемо об'єднати два списки, об'єкт, що виходить, міститиме список списків.

a = [1,2]
b = [3]
a.append(b)
print (a)
[1,2,[3]]

Якщо ми спробуємо отримати доступ до елемента в позиції 2, ми отримаємо список ([3]) замість елемента. Щоб приєднатися до двох списків, нам доведеться скористатися додатком.

a = [1,2]
b = [3]
a.extend(b)
print (a)
[1,2,3]

Щоб приєднатися до кількох списків

a = [1]
b = [2]
c = [3]
a.extend(b+c)
print (a)
[1,2,3]

2
Чому ви відповідаєте на питання, на яке вже багато разів відповідали? Цьому питанню 10 років ...
Майк - SMT
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.