Методы append и extend в Python: в чем разница

Методы append и extend в Python: в чем разница


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


Зачем пополнять списки


Список — самая ходовая структура данных в Python, и почти всегда он не задан заранее, а собирается по ходу программы. Вы фильтруете строки лога и складываете подходящие в отдельный список. Читаете ответ от сервера и добавляете новые записи к уже имеющимся. Проходите по каталогу товаров и собираете те, что дешевле лимита.


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


Метод append: добавляем один элемент


Синтаксис предельно простой:


список.append(элемент)


Метод берет то, что вы передали, и кладет в конец списка как один целый элемент. Длина списка при этом увеличивается ровно на единицу.


courses = ["Python", "Frontend"]


courses.append("QA")


print(courses)


# ['Python', 'Frontend', 'QA']


Передать можно объект любого типа: число, строку, словарь, кортеж, другой список, экземпляр класса.


mixed = []


mixed.append(42)


mixed.append("текст")


mixed.append({"id": 1})


print(mixed)


# [42, 'текст', {'id': 1}]


Метод принимает ровно один аргумент. Попытка передать два выдаст ошибку:


courses.append("QA", "Python")


# TypeError: list.append() takes exactly one argument (2 given)


Почему append возвращает None


Это первая ловушка, в которую попадают почти все новички. append() работает на месте: он изменяет существующий список, а не создает новый, и поэтому ничего не возвращает.


courses = ["Python"]


result = courses.append("QA")


print(result) # None


print(courses) # ['Python', 'QA']


Отсюда типичная ошибка:


courses = courses.append("QA") # так делать нельзя


print(courses) # None — список потерян


Запомните: методы, изменяющие список на месте — append, extend, insert, sort, reverse, — возвращают None. Их результат не присваивают, метод просто вызывают.


append в цикле: собираем список по частям


Самый частый сценарий использования — накопление результата в цикле.


temperatures = [25, 30, 18, 22, 27]


hot_days = []


for temp in temperatures:


if temp > 25:


hot_days.append(temp)


print(hot_days) # [30, 27]


Для простых случаев вроде этого в Python есть более короткая запись — генератор списка:


hot_days = [temp for temp in temperatures if temp > 25]


Он делает то же самое, читается компактнее и работает чуть быстрее. Но как только внутри цикла появляется несколько условий или дополнительные вычисления, обычный цикл с append понятнее — не гонитесь за краткостью в ущерб читаемости.


append со списком: получаем вложенность


Ключевой момент, ради которого чаще всего и ищут эту тему. Если передать в append список, он добавится целиком, одним элементом:


list1 = [1, 2, 3]


list2 = [4, 5, 6]


list1.append(list2)


print(list1)


# [1, 2, 3, [4, 5, 6]]


print(len(list1))


# 4 — не 6


Последний элемент теперь сам является списком. Обратиться к четверке можно только через двойной индекс: list1[3][0].


Иногда это ровно то, что нужно — например, когда вы строите таблицу, где каждая строка это список:


table = []


table.append(["Азиз", 85])


table.append(["Дилноза", 92])


print(table)


# [['Азиз', 85], ['Дилноза', 92]]


Но если задача была склеить два списка в один плоский, нужен другой метод.


Метод extend: добавляем несколько элементов


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


list1 = [1, 2, 3]


list2 = [4, 5, 6]


list1.extend(list2)


print(list1)


# [1, 2, 3, 4, 5, 6]


print(len(list1))


# 6


Список остается плоским, вложенности не возникает. По результату extend эквивалентен циклу с append:


for item in list2:


list1.append(item)


Только записывается одной строкой и работает быстрее.


Что можно передать в extend


Аргументом может быть любой итерируемый объект, а не только список.


data = [1, 2]


data.extend((3, 4)) # кортеж


data.extend({5, 6}) # множество


data.extend(range(7, 9)) # диапазон


print(data)


# [1, 2, 3, 4, 5, 6, 7, 8]


С множеством есть нюанс: элементы в нем не упорядочены, поэтому порядок добавления не гарантирован. Если порядок важен, отсортируйте множество перед добавлением.


Словарь тоже итерируемый объект, но перебирается он по ключам, а не по парам:


data = []


data.extend({"name": "Азиз", "city": "Ташкент"})


print(data)


# ['name', 'city']


Если нужны значения, передавайте data.extend(person.values()).


Ловушка первая: extend со строкой


Строка в Python — это последовательность символов, а значит, итерируемый объект. extend честно разберет ее на буквы:


words = ["привет"]


words.extend("мир")


print(words)


# ['привет', 'м', 'и', 'р']


Почти наверняка вы хотели получить ['привет', 'мир']. Для добавления строки целиком нужен append:


words = ["привет"]


words.append("мир")


print(words)


# ['привет', 'мир']


Это, пожалуй, самая частая ошибка при работе с этими методами.


Ловушка вторая: extend с числом


Число не является итерируемым объектом, поэтому передать его в extend нельзя:


numbers = [1, 2]


numbers.extend(3)


# TypeError: 'int' object is not iterable


Если нужно добавить одно число, берите append. Если хотите остаться с extend, оберните значение в список: numbers.extend([3]).


В чем разница append и extend: сводка


  • Что принимают. append — любой объект. extend — только итерируемый.
  • Сколько добавляют. append — ровно один элемент. extend — столько, сколько элементов в переданном объекте.
  • Насколько вырастает список. У append всегда на единицу. У extend — на длину аргумента.
  • Со списком в аргументе. append создает вложенный список. extend склеивает плоско
  • Со строкой в аргументе. append добавляет строку целиком. extend разбирает ее на символы.
  • Что возвращают. Оба возвращают None и меняют исходный список на месте.



Другие способы добавить элементы


Кроме двух основных методов есть еще несколько вариантов, и каждый решает свою задачу.

insert вставляет элемент по указанному индексу, а не в конец:


courses = ["Python", "QA"]


courses.insert(1, "Frontend")


print(courses)


# ['Python', 'Frontend', 'QA']


Первый аргумент — позиция, второй — элемент. Чтобы вставить в начало, используйте индекс 0.


Оператор плюс склеивает два списка, но создает новый объект, не трогая исходные:


list1 = [1, 2]


list2 = [3, 4]


result = list1 + list2


print(result) # [1, 2, 3, 4]


print(list1) # [1, 2] — не изменился


Оператор плюс-равно работает иначе: он меняет список на месте и по поведению совпадает с extend:


list1 = [1, 2]


list1 += [3, 4]


print(list1) # [1, 2, 3, 4]


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


Присваивание срезу позволяет вставить сразу несколько элементов в любое место:


numbers = [1, 2, 5, 6]


numbers[2:2] = [3, 4]


print(numbers) # [1, 2, 3, 4, 5, 6]


Запись выглядит непривычно, зато это единственный способ вставить группу элементов в середину одной операцией.


Что работает быстрее


Для небольших списков разница незаметна, но на больших объемах она становится существенной.


append добавляет элемент за постоянное время: список в Python хранит запас свободных ячеек, и добавление в конец обычно не требует переноса данных.


extend работает пропорционально длине добавляемого объекта — по сути, это тот же цикл, только выполненный внутри интерпретатора, а не в вашем коде. Поэтому склеить два списка через extend быстрее, чем прогонять цикл с append вручную.


insert в начало списка медленный: чтобы освободить нулевую позицию, приходится сдвигать все остальные элементы. Если задача требует частого добавления в начало, используйте не список, а deque из модуля collections:


from collections import deque


queue = deque([2, 3])


queue.appendleft(1) # добавить один элемент в начало


queue.extendleft([0]) # добавить несколько в начало


queue.append(4) # добавить в конец


print(queue)


# deque([0, 1, 2, 3, 4])


Обратите внимание: у deque есть append и appendleft, а метода appendright не существует — это распространенная опечатка в статьях. Для добавления в конец используется обычный append.


Отдельно стоит запомнить антипаттерн: склеивать списки в цикле через оператор плюс.


result = []


for chunk in chunks:


result = result + chunk # медленно


Каждая итерация создает новый список и копирует все накопленное. На тысяче итераций это заметно тормозит. Правильный вариант — result.extend(chunk).


Списки хранят ссылки, а не копии


Есть неочевидное следствие того, как устроены списки. Когда вы добавляете в список изменяемый объект, туда попадает ссылка на него. Изменится оригинал — изменится и то, что вы видите в списке.


inner = [1, 2]


outer = []


outer.append(inner)


inner.append(3)


print(outer)


# [[1, 2, 3]] — изменился и вложенный список


Если такое поведение нежелательно, добавляйте копию:


outer.append(inner.copy())


С числами и строками этой проблемы нет: они неизменяемы, и переприсваивание переменной на содержимое списка не влияет.


Частые ошибки новичков


Присваивание результата. my_list = my_list.append(x) уничтожает список, записывая в переменную None.


extend вместо append для строки. Строка разбирается на символы вместо добавления целиком.


append вместо extend для списка. Появляется лишний уровень вложенности, и len() показывает не то число, которое ожидалось.


Изменение списка во время перебора. Добавление элементов внутрь цикла, который идет по этому же списку, приводит к непредсказуемому поведению вплоть до бесконечного цикла. Собирайте результат в отдельный список.


# так делать нельзя


for item in items:


if item > 0:


items.append(item)


Вызов метода у не-списка. У кортежа методов append и extend нет, потому что кортеж неизменяемый. Ошибка AttributeError: 'tuple' object has no attribute 'append' означает именно это.


Что выбрать: короткая шпаргалка


  • Добавить одно значение в конец — append(x)
  • Добавить строку целиком — append("текст")
  • Склеить два списка в один плоский — extend(other) или +=
  • Получить новый список, не трогая исходные — list1 + list2
  • Вставить элемент в середину или начало — insert(index, x)
  • Вставить сразу несколько в середину — присваивание срезу
  • Часто добавлять в начало — deque и appendleft
  • Собрать список по условию из другого — генератор списка



Коротко о главном


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


Оба метода меняют список на месте и возвращают None, поэтому их результат никогда не присваивают. Рядом стоят insert для вставки по индексу, оператор + для создания нового списка и += для изменения существующего.



Списки и работа с ними — база, без которой не обойтись ни в парсинге, ни в анализе данных, ни в написании ботов. Освоить Python с нуля до уровня реальных проектов можно на курсе Python в PROWEB — 8 месяцев, с 14 лет, с практикой и поддержкой в трудоустройстве. Если вы еще выбираете направление в IT, пройдите бесплатный IT-тест — он подскажет, что вам ближе.


Часто задаваемые вопросы


В чем разница между append и extend?


append добавляет переданный объект как один элемент, поэтому список вырастает на единицу. extend перебирает переданную последовательность и добавляет каждый ее элемент отдельно, поэтому список вырастает на длину аргумента. Со списком в аргументе первый метод создает вложенность, а второй склеивает плоско.


Почему append возвращает None?


Потому что метод изменяет существующий список на месте, а не создает новый. Возвращать ему нечего. То же самое верно для extend, insert, sort и reverse — результат этих методов не присваивают переменной.


Как добавить один список в другой без вложенности?


Методом extend или оператором +=. Оба варианта добавят элементы по одному и оставят список плоским. Если исходные списки менять нельзя, используйте list1 + list2 — эта операция вернет новый список.


Почему extend разбивает строку на буквы?


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


Можно ли передать в append несколько элементов?


Нет, метод принимает ровно один аргумент. Попытка передать два вызовет TypeError. Для добавления нескольких значений используйте extend или цикл.


Чем insert отличается от append?


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


Что быстрее: extend или цикл с append?


extend быстрее, потому что перебор происходит внутри интерпретатора, а не в вашем коде на Python. Разница заметна на больших объемах данных. А вот склеивание списков через оператор + в цикле — самый медленный вариант, его лучше избегать.


Почему у кортежа нет метода append?


Потому что кортежи неизменяемы: после создания добавить или удалить элемент нельзя. Если нужна коллекция, которая будет меняться, используйте список.


Как добавить элемент в начало списка?


Методом insert(0, элемент). Если такая операция выполняется часто, вместо списка стоит взять deque из модуля collections — у него есть метод appendleft, который работает быстрее.



Другие статьи