Программирование и IT

Python: списки

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

Обновлено
В этой статье

Как создать и что внутри#

Список записывается в квадратных скобках; элементы могут быть разных типов, и
это нормально, хотя в реальном коде однородный список удобнее.

nums = [3, 1, 2]
mixed = [1, "два", 3.0, [4]]
empty = []
print(len(nums), nums[0], nums[-1])   # 3 3 2

Индексация с нуля, отрицательные индексы считают с конца: -1 — последний
элемент. Обращение за границу даёт IndexError, а не пустое значение.

Добавить и убрать#

items = ["a", "b"]
items.append("c")          # ['a', 'b', 'c']
items.extend(["d", "e"])   # ['a', 'b', 'c', 'd', 'e']
items.insert(1, "x")       # ['a', 'x', 'b', 'c', 'd', 'e']
items.remove("x")          # убирает ПЕРВОЕ вхождение
last = items.pop()         # 'e', список стал короче
print(items, last)         # ['a', 'b', 'c', 'd'] e

Разницу между append и extend стоит запомнить сразу: первый кладёт аргумент
одним элементом, второй раскрывает его по элементам.

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

remove бросает ValueError, если значения нет, а pop(i)IndexError при
неверном индексе. Чтобы удалить по индексу без возврата значения, есть del items[0].

Сортировка: sort и sorted#

words = ["слива", "Арбуз", "дыня"]
print(sorted(words, key=len))      # ['дыня', 'слива', 'Арбуз']
print(sorted(words, reverse=True)) # ['слива', 'дыня', 'Арбуз']
print(words.sort())                # None
print(words)                       # ['Арбуз', 'дыня', 'слива']

Метод sort меняет список на месте и возвращает None — строка
words = words.sort() превращает список в None, и это частая ошибка. Функция
sorted возвращает новый список и работает с любой последовательностью.
Аргумент key задаёт, по какому значению сравнивать: key=len — по длине,
key=str.lower — без учёта регистра. Заглавная буква сравнивается по коду
символа и потому оказывается раньше строчных: Арбуз встал перед дыня.
Сортировка устойчива — равные по ключу элементы сохраняют исходный порядок:
в примере с key=len пятибуквенные слива и Арбуз остались в том же
порядке, что были.

Копирование: присваивание не копирует#

a = [1, 2, 3]
b = a
b.append(4)
print(a)        # [1, 2, 3, 4]  — изменился и a

c = a.copy()    # или list(a), или a[:]
c.append(5)
print(a, c)     # [1, 2, 3, 4] [1, 2, 3, 4, 5]

b = a даёт второе имя тому же объекту. Настоящая копия — a.copy(), list(a)
или срез a[:]. Но все три копии поверхностные: вложенные списки останутся
общими.

table = [[0, 0], [0, 0]]
shallow = table.copy()
shallow[0][0] = 9
print(table)    # [[9, 0], [0, 0]]

Для глубокой копии берут copy.deepcopy. По той же причине опасна запись
grid = [[0] * 3] * 3: внешний список получает три ссылки на одну строку, и
grid[0][0] = 1 меняет все три. Правильно — [[0] * 3 for _ in range(3)].

Списочные выражения и перебор#

squares = [x * x for x in range(5)]
print(squares)                                # [0, 1, 4, 9, 16]
print([x for x in squares if x % 2 == 0])     # [0, 4, 16]

for i, value in enumerate(["a", "b"], start=1):
    print(i, value)                           # 1 a / 2 b

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

Отдельная ловушка — менять список, пока по нему идёт цикл:

nums = [1, 2, 2, 3]
for n in nums:
    if n == 2:
        nums.remove(n)
print(nums)     # [1, 2, 3] — одна двойка уцелела

Цикл идёт по индексам, а список после удаления сдвинулся. Правильный приём —
собрать новый список: nums = [n for n in nums if n != 2].

Задание для закрепления: из списка оценок [4, 5, 3, 5, 4, 2] получи список
без повторов, отсортированный по убыванию, и отдельно — количество оценок выше
тройки. Оба ответа умещаются в одну строку каждый.

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

План по этапам

  1. Создать и обойтиСписок из десяти чисел, печать длины, первого и последнего элемента, перебор через enumerate.
  2. Пять методов измененияappend, extend, insert, remove, pop — после каждого печатать список и видеть разницу.
  3. Сортировка тремя способамиsort, sorted, sorted с key=len; убедиться, что sort вернул None.
  4. Эксперимент с копиейb = a и c = a.copy(): изменить каждую и сравнить, что стало с a.
  5. Переписать цикл выражениемЗаменить цикл с append на списочное выражение с условием.

Начать изучать эту тему у себя

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

Начать план

Проверь себя

1.Что выведет: a = [1, 2]; a.append([3, 4]); print(len(a))?

2.Что выведет print([1, 2, 3].sort())?

3.Что выведет: a = [1, 2]; b = a; b.append(3); print(a)?

4.Чему равно len([x for x in range(10) if x % 3 == 0])?

Источники

Было полезно?

Ещё темы

Программирование и IT Python: строки Строка в Python — неизменяемая последовательность символов. Из этого следуют почти все её особенности: методы не меняют строку, а возвращают новую, а быстрая сборка текста идёт через join, а не через сложение в цикле. Ниже — рабочий минимум с примерами и выводом. Программирование и IT Python: словари Словарь хранит пары «ключ — значение» и находит значение по ключу за постоянное время независимо от размера. Это рабочая лошадка для подсчётов, группировок и настроек. Разберём создание, безопасный доступ, перебор и места, где словарь ведёт себя не так, как ожидают. Программирование и IT Python: срезы Срез вырезает из последовательности кусок по правилу «с какого индекса, до какого, с каким шагом». Запись компактная, но у неё два места, где почти все ошибаются: правая граница не включается, а при отрицательном шаге границы меняются местами. Разберём оба. Программирование и IT Как изучить Python с нуля Python хорош для первого знакомства с программированием: код читается почти как текст, а стандартная библиотека закрывает большинство бытовых задач. Этот план ведёт от установки интерпретатора до собственных скриптов, покрытых тестами, — примерно за четыре месяца при занятиях около часа в день. Программирование и IT git branch Ветка в git — это подвижный указатель на коммит, а не копия файлов. Поэтому завести её ничего не стоит, а команда git branch отвечает за список веток, их создание, переименование и удаление. Программирование и IT Python: генераторы Генератор выдаёт значения по одному и только тогда, когда их просят. Он не хранит всю последовательность в памяти, поэтому подходит для больших файлов и бесконечных потоков. Плата за это — генератор одноразовый: пройти по нему дважды не получится.

Ещё сценарии