Код
#статьи

Списки в Python: что это такое и как с ними работать

Рассказали всё самое важное о списках для тех, кто только становится «змееустом».

Иллюстрация: Оля Ежак для Skillbox Media

Сегодня мы подробно поговорим о, пожалуй, самых важных объектах в Python — списках. Разберём, зачем они нужны, как их использовать и какие удобные функции есть для работы с ними.

В статье есть всё, что начинающим разработчикам нужно знать о списках в Python:


Что такое списки

Список (list) — это упорядоченный набор элементов, каждый из которых имеет свой номер, или индекс, позволяющий быстро получить к нему доступ. Нумерация элементов в списке начинается с 0: почему-то так сложилось в C, а C — это база. Теорий на этот счёт много — на «Хабре» даже вышло большое расследование :)

Так списки можно представить визуально
Иллюстрация: Оля Ежак для Skillbox Media

В одном списке одновременно могут лежать данные разных типов — например, и строки, и числа. А ещё в один список можно положить другой и ничего не сломается:

Мы положили в список число, строку и кота. Всё работает
Иллюстрация: Оля Ежак для Skillbox Media

Все элементы в списке пронумерованы. Мы можем без проблем узнать индекс элемента и обратиться по нему.

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

Добавили новый элемент — мышь — и изменили первый элемент на 8
Иллюстрация: Оля Ежак для Skillbox Media

Когда мы создаём объект list, в памяти компьютера под него резервируется место. Нам не нужно переживать о том, сколько выделяется места и когда оно освобождается, — Python всё сделает сам. Например, когда мы добавляем новые элементы, он выделяет память, а когда удаляем старые — освобождает.

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

Однако в списках Python можно хранить объекты разного размера и типа. Более того, размер массива ограничен, а размер списка в Python — нет. Но всё равно мы знаем, сколько у нас элементов, а значит, можем обратиться к любому из них с помощью индексов.

И тут есть небольшой трюк: списки в Python представляют собой массив ссылок. Да-да, решение очень элегантное — каждый элемент такого массива хранит не сами данные, а ссылку на их расположение в памяти компьютера!

Как создать список в Python

Чтобы создать объект list, в Python используют квадратные скобки — []. Внутри них перечисляют элементы через запятую:

a = [1, 2, 3]

Мы создали список a и поместили в него три числа, которые разделили запятыми. Давайте выведем его с помощью функции print():

print(a)

>>> [1, 2, 3]

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

Мы уже говорили, что списки могут хранить данные любого типа. В примере ниже объект b хранит: строку — cat, число — 123 и булево значение — True:

b = ['cat', 123, True]

print(b)

>>> ['cat', 123, True]

Также в Python можно создавать вложенные списки:

c = [1, 2, [3, 4]]

print(c)

>>> [1, 2, [3, 4]]

Мы получили объект, состоящий из двух чисел — 1 и 2 — и вложенного list с двумя элементами — [3, 4].

Операции со списками

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

Индексация

Доступ к элементам списка получают по индексам, через квадратные скобки []:

a = [1, 2, 3]

print(a[1])

>>> 2

Мы обратились ко второму элементу и вывели его с помощью print().

Здесь важно помнить две вещи:

  • у каждого элемента есть свой индекс;
  • индексы начинаются с 0.

Давайте ещё поиграем с индексами:

a = [1, 2, 3, 4]

a[0] # Обратится к 1
a[2] # Обратится к 3
a[3] # Обратится к 4
a[4] # Выведет ошибку

В последней строке мы обратились к несуществующему индексу, поэтому Python выдал ошибку.

Кроме того, Python поддерживает обращение к нескольким элементам сразу — через интервал. Делается это с помощью двоеточия — :.

a = [1, 2, 3, 4]

a[0:2] # Получим [1, 2]

Двоеточие позволяет получить срез списка. Полная форма оператора выглядит так: начальный_индекс:конечный_индекс:шаг.

Здесь мы указываем, с какого индекса начинается «срез», на каком заканчивается и с каким шагом берутся элементы — по умолчанию 1. Единственный нюанс с конечным индексом: хоть мы и можем подумать, что закончим именно на нём, на самом деле Python остановится на элементе с индексом конечный_индекс — 1. Почему создатели языка решили так сделать? Кто их знает.

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

Усложним пример:

a = [1, 2, 3, 4, 5]

a[1:6:2] # Получим [2, 4]

Здесь мы шли по элементам с шагом 2. Начали с индекса 1 — это первое число внутри скобок, а закончили на индексе 6, не включая его. Двигались с шагом 2, то есть через один элемент, и получили [2, 4].

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

Изменение элементов

Списки — это динамическая структура данных. А значит, мы можем менять их уже после создания.

Например, можно заменить один элемент на другой:

a = [1, 2, 3]
a[1] = 4

print(a)
 
>>> [1, 4, 3]

Мы обратились к элементу по индексу и заменили его на число 4. Всё прошло успешно, список изменился.

Но нужно быть осторожными, потому что может случиться такое:

a = [1, 2]
b = a
a[0] = 5

print(a)
print(b)

>> [5, 2]
>> [5, 2]

Сначала мы создали список a с двумя элементами — 1 и 2. Затем объявили переменную b и присвоили ей содержимое a. Потом заменили первый элемент в a и… удивились, что он заменился и в b.

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

Когда мы присваиваем переменной список, на самом деле мы присваиваем ей ссылку на первый элемент списка
Иллюстрация: Оля Ежак для Skillbox Media

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

Поэтому, когда мы присвоили списку b список a, то на самом деле присвоили ему ссылку на первый элемент — по сути, сделав их одним списком.

Объединение списков

Иногда полезно объединить два списка. Чтобы это сделать, используют оператор +:

a = [1, 2]
b = [3, 4]
с = a + b

print(с)

>>> [1, 2, 3, 4]

Мы создали два списка — a и b. Затем переприсвоили a новым списком, который стал объединением старого a и b.

Разложение списка

Элементы списка можно присвоить отдельным переменным:

a = [1, 2, 3]
d1, d2, d3 = a

print(d1)
print(d2)
print(d3)

>>> 1
>>> 2
>>> 3

Здесь из списка a поочерёдно достаются элементы, начиная с индекса 0, и присваиваются переменным. И в отличие от присвоения одного списка другому, в этом случае Python создаст три отдельных целых числа, которые никак не будут связаны с элементами списка, и присвоит их трём переменным. Поэтому, если мы изменим, например, переменную d2, со списком a ничего не случится.

Перебор элементов

Мы можем перебирать элементы списка с помощью циклов for и while.

Так выглядит перебор через for:

animals = ['cat', 'dog', 'bat']
for animal in animals:
  print(animal)

>>> cat
>>> dog
>>> bat

Здесь мы перебираем каждый элемент списка и выводим их с помощью функции print().

А вот так выглядит перебор через цикл while:

animals = ['cat', 'dog', 'bat']
i = 0
while i < len(animals):
  print(animals[i])
  i += 1

>>> cat
>>> dog
>>> bat

Этот перебор чуть сложнее, потому что мы используем дополнительную переменную i, чтобы обращаться к элементам списка. Также мы использовали встроенную функцию len(), чтобы узнать размер нашего списка. А ещё в условии цикла while мы указали знак «меньше» (<), потому что индексация элементов идёт до значения количество элементов списка — 1. Как и в прошлом примере, все элементы по очереди выводятся с помощью функции print().

Сравнение списков

Python поддерживает сравнение списков. Два списка считаются равными, если они содержат одинаковые элементы. Функция возвращает булево значение — True или False:

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

>>> True

Получили, что списки равны.

В некоторых языках равенство ещё проверяется и по тому, ссылаются ли переменные на один и тот же объект. Обычно это делается через оператор ===. В Python это можно сделать через оператор is, который проверяет, имеют ли две переменные один и тот же адрес в памяти:

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

>>> True

Получили, что две переменные ссылаются на один и тот же адрес в памяти.

Встроенные функции для списков Python

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

len()

Возвращает длину списка:

a = [5, 3, 1]
len(a) # 3

sorted()

Возвращает отсортированный список:

a = [8, 1, 3, 2]
sorted(a) # [1, 2, 3, 8]

min() и max()

Возвращают наименьший и наибольший элемент списка:

a = [1, 9, -2, 3]
min(a) # -2
max(a) # 9

Методы списков Python

Чтобы проще управлять элементами списка, в стандартной библиотеке Python есть набор популярных методов для списков. Разберём основные из них.

append()

Добавляет новый элемент в конец списка:

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

>>> [1, 2, 3, 4]

extend()

Добавляет набор элементов в конец списка:

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

>>> [1, 2, 3, 4, 5]

Внутрь метода extend() нужно передать итерируемый объект — например, другой list или строку.

Вот так метод extend() добавит строку:

a = ['cat', 'dog', 'bat']
a.extend('mouse')
print(a)

>>> ['cat', 'dog', 'bat', 'm', 'o', 'u', 's', 'e']

Заметьте, что строка добавилась посимвольно.

insert()

Добавляет новый элемент по индексу:

a = [1, 2, 3]
a.insert(0, 4)
print(a)

>>> [4, 1, 2, 3]

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

remove()

Удаляет элемент из списка:

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

>>> [2, 3, 1]

Метод удаляет только первое вхождение элемента. Остальные остаются нетронутыми.

Если элемента нет в списке, Python вернёт ошибку и программа прервётся:

a = [1, 2, 3, 1]
a.remove(5)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: list.remove(x): x not in list

Ошибка говорит, что элемента нет в списке.

clear()

Удаляет все элементы из списка и делает его пустым:

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

>>> []

index()

Возвращает индекс элемента списка в Python:

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

>>> 1

Если элемента нет в списке, выведется ошибка:

a = [1, 2, 3]
print(a.index(4))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: 4 is not in list

pop()

Удаляет элемент по индексу и возвращает его как результат:

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

>>> 3
>>> [1, 2]

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

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

>>> 2
>>> [1, 3]

count()

Считает, сколько раз элемент повторяется в списке:

a = [1, 1, 1, 2]
print(a.count(1)) 

>>> 3

sort()

Сортирует список:

a = [4, 1, 5, 2]
a.sort() # [1, 2, 4, 5]

Если нам нужно отсортировать в обратном порядке — от большего к меньшему, — в методе есть дополнительный параметр reverse:

a = [4, 1, 5, 2]
a.sort(reverse=True) # [5, 4, 2, 1]

reverse()

Переставляет элементы в обратном порядке:

a = [1, 3, 2, 4]
a.reverse() # [4, 2, 3, 1]

copy()

Копирует список:

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

print(b)

>>> [1, 2, 3]

Для того чтобы быстро находить нужные методы во время работы, пользуйтесь этой шпаргалкой:

МетодЧто делает
a.append(x)Добавляет элемент x в конец списка a. Если x — список, то он появится в a как вложенный
a.extend(b)Добавляет в конец a все элементы списка b
a.insert(i, x)Вставляет элемент x на позицию i
a.remove(x)Удаляет в a первый элемент, значение которого равно x
a.clear()Удаляет все элементы из списка a и делает его пустым
a.index(x)Возвращает индекс элемента списка
a.pop(i)Удаляет элемент по индексу и возвращает его
a.count(x)Считает, сколько раз элемент повторяется в списке
a.sort()Сортирует список. Чтобы отсортировать элементы в обратном порядке, нужно установить дополнительный аргумент reverse=True
a.reverse()Возвращает обратный итератор списка a
a.copy()Создаёт поверхностную копию списка. Для создания глубокой копии используйте метод deepcopy из модуля copy

Что запомнить

Лучше не учить это всё, а применять на практике. А ещё лучше — попытаться написать каждый метод самостоятельно, не используя никакие встроенные функции.

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

Больше интересного про код в нашем телеграм-канале. Подписывайтесь!

Изучайте IT на практике — бесплатно

Курсы за 2990 0 р.

Я не знаю, с чего начать
Научитесь: Профессия Python-разработчик Узнать больше
Понравилась статья?
Да

Пользуясь нашим сайтом, вы соглашаетесь с тем, что мы используем cookies 🍪

Ссылка скопирована