2.7. Списки

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

2.7.1. Создание списков

Квадратные скобки создают литерал списка:

empty   = []
nums    = [1, 2, 3]
mixed   = [1, "two", 3.0, True, None]    # any types
nested  = [[1, 2], [3, 4], [5, 6]]       # lists of lists

Конструктор list строит список из любого итерируемого объекта:

>>> list("abc")
['a', 'b', 'c']
>>> list(range(5))
[0, 1, 2, 3, 4]

2.7.2. Длина, индексация и срезы

len() возвращает количество элементов. Индексация и срезы работают так же, как у строк — позиции начинаются с 0, отрицательные индексы отсчитываются с конца, а срез за пределами допустимого диапазона молча обрезается, а не вызывает ошибку:

>>> nums = [10, 20, 30, 40, 50]
>>> len(nums)
5
>>> nums[0]
10
>>> nums[-1]
50
>>> nums[1:4]
[20, 30, 40]
Список из шести ячеек с положительными индексами 0..5 сверху и отрицательными индексами -6..-1 под каждой ячейкой.

Положительные индексы отсчитываются с начала; отрицательные индексы отсчитываются с конца.

Синтаксис срезов — это сокращение для объекта slice, который Python создаёт за кулисами. nums[1:4] — это то же самое, что nums[slice(1, 4)]. Вы редко создаёте его вручную, но slice() иногда полезен для хранения среза как значения для повторного использования:

head = slice(0, 3)
print(nums[head])             # [10, 20, 30]
print(letters[head])          # first three letters, same slice

2.7.3. Изменение списка

Списки поддерживают присваивание по индексу и по срезу на месте:

>>> nums = [10, 20, 30]
>>> nums[0] = 99
>>> nums
[99, 20, 30]
>>> nums[1:3] = [200, 300, 400]    # slice can change the length
>>> nums
[99, 200, 300, 400]

Наиболее распространённые методы списков:

  • list.append() — добавить один элемент в конец.

  • list.extend() — добавить каждый элемент из итерируемого объекта.

  • list.insert() — вставить в заданную позицию.

  • list.remove() — удалить первое вхождение значения.

  • list.pop() — удалить и вернуть элемент (по умолчанию последний).

  • list.clear() — удалить все элементы.

  • list.sort() — отсортировать на месте. Передайте reverse=True для убывающего порядка.

  • list.reverse() — перевернуть на месте.

>>> nums = []
>>> nums.append(1)
>>> nums.extend([2, 3])
>>> nums.insert(0, 99)
>>> nums
[99, 1, 2, 3]
>>> nums.pop()
3
>>> nums.sort()
>>> nums
[1, 2, 99]

Эти методы изменяют список на месте и возвращают None. Запись

nums = nums.sort()    # nums is now None -- common bug

почти никогда не является тем, что вам нужно; исходный nums был отсортирован, но затем присваивание перезаписывает имя возвращаемым значением. Либо вызовите nums.sort() на отдельной строке, либо используйте встроенную функцию sorted(), чтобы получить новый отсортированный список без изменения оригинала.

2.7.4. Операторы

  • + объединяет два списка в новый список.

  • * повторяет список.

  • in проверяет принадлежность.

>>> [1, 2] + [3, 4]
[1, 2, 3, 4]
>>> [0] * 5
[0, 0, 0, 0, 0]
>>> 3 in [1, 2, 3]
True

2.7.5. Итерация по списку

Цикл for проходит по элементам по порядку:

for n in [10, 20, 30]:
    print(n)

2.7.6. Псевдонимы и изменение

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

Две переменные a и b, обе указывающие на один и тот же объект-список; добавление к a видно через b.

a и b обе указывают на один и тот же список. Изменение через любое из имён меняет то, что видят все остальные имена.

>>> a = [1, 2, 3]
>>> b = a
>>> a.append(4)
>>> b
[1, 2, 3, 4]                # same object, change is visible

Чтобы создать независимую копию, сделайте срез всего списка или вызовите конструктор list:

>>> c = a[:]                # or list(a)
>>> a.append(5)
>>> c
[1, 2, 3, 4]                # c is unaffected

Это копирует только список верхнего уровня; вложенные списки по-прежнему являются общими между оригиналом и копией.