Перейти к содержанию

432 уроков, 26 библиотек и челлендж «Что выведет код?» — бесплатно, код прямо в браузере

Начать обучение
Урок 2 из 20 Начальный 15 мин 100 XP

Python append: добавляем элемент в конец списка

append кладёт один элемент в конец списка и меняет список на месте. Метод возвращает None — поэтому строка nums = nums.append(x) теряет список.

Редакция Питоники

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

Первый append: один элемент в конец

Метод вызывается через точку после имени списка: cart.append('сыр'). Элемент дописывается в самый конец, остальные не двигаются:

append добавляет в конец
cart = ['хлеб', 'молоко']
cart.append('сыр')
print(cart)
print(len(cart))
Вывод
['хлеб', 'молоко', 'сыр']
3

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

append принимает ровно один аргумент
cart = ['хлеб']
cart.append('сыр', 'сок')
Вывод
Traceback (most recent call last):
  File "app.py", line 2, in <module>
    cart.append('сыр', 'сок')
    ~~~~~~~~~~~^^^^^^^^^^^^^^
TypeError: list.append() takes exactly one argument (2 given)
Путь к файлу в traceback условный, у вас он будет свой. Пачку элементов добавляет extend — о нём следующий урок.

Пачки добавляет extend — о нём следующий урок.

append меняет список на месте

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

что вернул append
cart = ['хлеб']
print(cart.append('молоко'))
print(cart)
Вывод
None
['хлеб', 'молоко']

Первая печать показала None — и это не поломка, а честный ответ метода. append возвращает None: вся его работа — изменить список, к которому его применили, поэтому отдавать результат он не может. Само изменение уже произошло, вторая печать это показывает: в cart теперь два товара. Новичок ожидает, что метод вернёт обновлённый список, и пишет присваивание — вот здесь список теряется:

классическая потеря списка
cart = ['хлеб']
cart = cart.append('молоко')
try:
    cart.append('сыр')
except AttributeError as e:
    print('Ошибка:', e)
Вывод
Ошибка: 'NoneType' object has no attribute 'append'

Строка cart = cart.append('молоко') записала в переменную None: добавление уже случилось, а присваивание затёрло список тем, что вернул метод, — ничем. Дальше по коду любая работа с cart падает, и сообщение всегда подозрительно упоминает NoneType. Без try/except та же история выглядит как обычный traceback:

так падает программа без try/except
cart = ['хлеб']
cart = cart.append('молоко')
print(len(cart))
Вывод
Traceback (most recent call last):
  File "app.py", line 3, in <module>
    print(len(cart))
          ~~~^^^^^^
TypeError: object of type 'NoneType' has no len()
Падает не сам append, а следующая строка: в cart лежит None. Путь к файлу в traceback условный, у вас он будет свой.

append кладёт ровно один элемент

Аргумент append становится одним элементом списка — каким бы значением он ни был. Передадим списком сразу два товара и посмотрим, что ляжет в корзину:

список в append становится одним элементом
cart = ['хлеб']
cart.append(['яйца', 'майонез'])
print(cart)
print(len(cart))
Вывод
['хлеб', ['яйца', 'майонез']]
2

Внутри корзины оказался не майонез и не яйца, а целый подсписок: длина выросла до двух, а не до трёх. append не разбирает аргумент на части — он кладёт его как единый элемент, и внутри корзины получился вложенный список. Такие списки-таблицы разбираются отдельно в уроке про список списков, а для добавления пачкой элементов нужен extend.

append в цикле: шаблон сборки результатов

Самый распространённый узор с append — сборка нового списка из цикла: заводят пустой список и на каждом шаге кладут в него очередной результат. Соберём цены со скидкой десять процентов:

пустой список и append в цикле
prices = [199, 89, 449]
with_discount = []
for price in prices:
    with_discount.append(round(price * 0.9))
print(with_discount)
print(len(with_discount))
Вывод
[179, 80, 404]
3

Исходный список prices не тронут — каждый шаг цикла положил результат в новый список with_discount. Пустой список плюс append в цикле — типовой шаблон сборки: начинаем с пустого списка и на каждом шаге кладём в него результат. Тот же шаблон собирает отбор: в новый список попадают только подходящие элементы,

отбор чётных чисел в новый список
nums = [3, 8, 5, 12, 7]
even = []
for n in nums:
    if n % 2 == 0:
        even.append(n)
print(even)
print(len(nums), len(even))
Вывод
[8, 12]
5 2

Из пяти чисел в новый список легли два чётных: append сработал только там, где условие пропустило значение. Исходный список не изменился — 5 против 2 в печати длин. Шаблон встречается в каждом втором скрипте обработки данных; в уроке про генератор списков покажут, как записывать его одной строкой.

Способы пополнить список

append — не единственный способ добавить данные, и важно различать их по задаче:

ЗадачаИнструментКак работает
Один элемент в конецappend(x)Длина растёт на 1, список меняется на месте
Пачка элементов из спискаextend(список)Раскладывает аргумент на элементы (урок 3)
Один элемент в серединуinsert(i, x)Вставка по индексу, остальные сдвигаются (урок 3)
Список с известными элементамилитерал [...]Записывается целиком одной строкой (урок 1)

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

append освоен: один элемент за вызов, в конец, на месте, без возврата. Остаётся второй способ пополнения — вставка по индексу и добавление пачкой: insert и extend из следующего урока закрывают обе задачи.

Что выведет код?

Сначала предскажи ответ в голове — это главный навык программиста.

nums = [1, 2]
nums.append(3)
nums.append(4)
print(nums)
print(len(nums))
cart = ['хлеб']
cart.append(['сыр', 'сок'])
print(len(cart))
log = []
for word in ['раз', 'два']:
    log.append(word)
print(log)
print(log.append('три'))
Проверь себя
0 / 6

1. Куда append добавляет элемент?

2. Что вернёт выражение cart.append('сыр')?

3. Что окажется в nums после nums = nums.append(4), если nums был [1, 2, 3]?

4. Что произойдёт после cart.append(['яйца', 'майонез']) для cart = ['хлеб']?

5. Сколько элементов можно добавить одним вызовом append?

6. Как правильно собрать список результатов в цикле?

Карточки терминов
Запомнено: 0 / 6
Практика

Соберите квадраты чисел: начните с пустого списка squares, в цикле for по числам от 1 до 5 добавьте их квадраты методом append и напечатайте получившийся список.

practice.py
Вопросы и ответы по уроку

Что делает append в Python?

Метод append добавляет один элемент в конец списка: cart.append('сыр') дописывает товар после последнего. Список меняется на месте, длина растёт на единицу, остальные элементы не сдвигаются. Метод возвращает None, поэтому его результат не присваивают переменной.

Урок 3: insert и extend

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

append — мутирующий метод: вся его работа — изменить список, к которому он применён. Возвращать обновлённую копию он не может, поэтому Python отдаёт None. Строка nums = nums.append(4) после добавления элемента записывает в переменную None, и падает уже следующий код со словом NoneType.

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

append кладёт аргумент одним элементом: [1].append([2, 3]) даёт [1, [2, 3]] длины 2. extend раскладывает аргумент на элементы: [1].extend([2, 3]) даёт [1, 2, 3] длины 3. По одному значению — append, пачкой — extend.

Урок 3: extend раскладывает пачку

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

Методом insert с индексом ноль: cart.insert(0, 'хлеб') вставит элемент первым и сдвинет остальные вправо. Для начала списка это дороже append: вставка двигает весь список. Альтернатива для очередей из стандартной библиотеки — deque.appendleft, о ней рассказывается в уроке про методы списков.

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

Методом extend от списка или кортежа: cart.extend(['яйца', 'сок']) допишет оба товара. Годится и цикл с append — по одному элементу за шаг; append со списком в аргументе не подходит: он сделает его одним вложенным элементом.

Урок 3: insert и extend

Понравился урок? Сошлитесь на него

«append возвращает None: вся его работа — изменить список, к которому его применили, поэтому отдавать результат он не может.»

Скопируйте готовую ссылку в формате HTML, Markdown или чистый адрес и вставьте в статью на Habr, VC, Telegram-канал или свой блог — так о проекте узнают новые читатели.

TelegramVK

Что дальше

Осталось в разделе: 20 из 20. Прогресс хранится в вашем браузере.

Похожие уроки по темам

Подобраны автоматически по пересечению тем и ключевых слов.