Списки

Списки (list) — это некоторое подобие массива в "привычных" вам языках программирования лишь с тем отличием, что в list могут храниться элементы разных типов. Давайте попробуем разобраться на примерах.

Базовые операции

Создание списка


In [1]:
a = [1, 2, "Hi"]         # Создать список и присвоить переменной `а` этот список
print(a[0], a[1], a[2])  # Обращение к элементам списка, индексация с нуля

b = list()               # Создать пустой список
c = []                   # Другой способ создать пустой список


1 2 Hi

Можно создать список из однотипных элементов заданной длины:


In [2]:
a = [0] * 10
print(a)


[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]

In [3]:
N = 5
b = [True] * N
print(b)


[True, True, True, True, True]

Доступ к элементам


In [4]:
a = [1, 2, "Hi"] 
a[1] = 4  # Изменить отдельный элемент списка
print(a)  # Вывести весь список


[1, 4, 'Hi']

Обратите внимание, что при выведении списка таким способом он выводится с квадратными скобками и запятыми.

В Python есть отрицательная индексация. −1 элемент это последний элемент, −2 элемент это предпоследний элемент списка и так далее:


In [5]:
a = [1, 2, "Hi"]
print(a[-1], '=', a[2])
print(a[-2], '=', a[1])
print(a[-3], '=', a[0])


Hi = Hi
2 = 2
1 = 1

In [6]:
b = ["a", 1, -2, [1, 2, 3], "b", 3.4]  # Элементом списка может быть список
print(b[-3])


[1, 2, 3]

Добавление элемента в конец

Метод append добавляет новый элемент в конец существующего списка:


In [7]:
a = [2, 3]
a.append(5)
print(a)


[2, 3, 5]

Длина списка

Функция len позволяет узнать длину (размер) списка:


In [8]:
a = [1, 3, 6]
print(len(a))


3

Сортировка

Метод sort сортирует текущий список по невозрастанию, если это возможно:


In [9]:
a = [3, 2, 4, 1, 2]
a.sort()
print(a)


[1, 2, 2, 3, 4]

Сложение

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


In [10]:
a = [1, 2, 3]
b = [4, 5, 6]
c = a + b
print(c)


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

Особенности присваивания списков

Во время выполнения интерпретатор хранит все данные, которые у вас есть в программе, как некоторый набор объектов. Примеры объектов:

  • 42 — число 42
  • "abc" — строка «abc»
  • "42" — строка «42»
  • 3.0 — вещественное число 3.0
  • False — логическое значение «Ложь»
  • ["abc", "42", 42] — список из нескольких других объектов

Переменная — это всего лишь ссылка на объект, который хранит интепретатор.

С учётом ссылочного устройства, посмотрим как происходит присваивание одного списка другому:


In [11]:
a = [1, 2, 3, 4]  # а - ссылка на список, каждый элемент списка это ссылки на объекты 1, 2, 3, 4
b = a             # b - ссылка на тот же самый список

# В Python у каждого объекта есть свой id (идентификатор) -
# некоторое уникальное число, сопоставленное объекту
print("id(a) = ", id(a))
print("id(b) = ", id(b))

a[0] = -1        # Меняем элемент списка a
print("b =", b)  # Значение b тоже поменялось!


id(a) =  140484292987400
id(b) =  140484292987400
b = [-1, 2, 3, 4]

Чтобы узнать как скопировать список, читайте страницу про срезы.

Почему то же самое не происходит с другими типами, например числами? Рассматривайте каждое отдельное число тоже как отдельный объект, на который может вести ссылка. Например, 2 это объект, и 3 это объект. При изменении значения переменной меняется только ссылка, а не объект.


In [12]:
a = 2
b = a
print("a =", a, ", id(a) =", id(a))
print("b =", b, ", id(b) =", id(b))
print()

a = 3
print("a =", a, ", id(a) =", id(a))
print("b =", b, ", id(b) =", id(b))


a = 2 , id(a) = 10935520
b = 2 , id(b) = 10935520

a = 3 , id(a) = 10935552
b = 2 , id(b) = 10935520

Списки и if

Преобразование к логическому значению

Пустой список преобразуется к логическому значению False:


In [13]:
lst = []
if lst:
    print("Ветка if")
else:
    print("Ветка else")


Ветка else

In [14]:
lst = []
if not lst:
     print("Ветка if")
else:
    print("Ветка else")


Ветка if

Непустой список преобразуется к True:


In [15]:
lst = [2, 3, 4]
if lst:
    print("Ветка if")
else:
    print("Ветка else")


Ветка if

In [16]:
lst = [[]]
if lst:
    print("Ветка if")
else:
    print("Ветка else")


Ветка if

Проверка наличия элемента в списке

Проверить, есть ли элемент в списке, можно с помощью оператора in. Это то же самое, что и пройти по всему списку и для каждого элемента проверить, не равен ли он искомому.


In [17]:
lst = [1, 6, 29, 4, "a", 3, -1]
if 3 in lst:
    print("3 is in the list")
else:
    print("3 is not in the list")


3 is in the list

Также есть аналогичный оператор not in, который проверяет, что элемента нет в списке:


In [18]:
lst = [1, 6, 29, 4, "a", 3, -1]
if 5 not in lst:
    print("5 is not in the list")


5 is not in the list

Списки и for

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


In [19]:
for i in [2, 3, 5, 7]:
    print(i)


2
3
5
7

In [20]:
lst = [3, "ads", [1, 2]]
for i in lst:
    print(i)


3
ads
[1, 2]

В каком-то смысле range тоже похож на list:


In [21]:
r = range(5)

print(r[2], r[-1])


2 4

Списки и строки

Split — разбиение строки

Метод split разбивает строку на список строк по выбранному разделяющему символу или нескольким символам. Например для разбивания строки по символу #:


In [22]:
s = "1#2#3"
print(s.split("#"))


['1', '2', '3']

По умолчанию (без параметров) split разбивает строку по пробельным символам, игнорируя подряд идущие пробельные символы:


In [23]:
names = "Artem    Irina  Zhenya"
print(names.split())


['Artem', 'Irina', 'Zhenya']

Пример строки-разделителя более чем из одной буквы:


In [24]:
s = "1abc2abcd3"
print(s.split("abc"))


['1', '2', 'd3']

Join — объединение строк

Метод join возвращает строку, в которой все элементы списка записаны через разделительный символ (символы). Каждый элемент списка обязательно должен быть строкой.


In [25]:
lst = ["1", "2", "3"]
print("#".join(lst))


1#2#3

Разделительная строка может быть пустой:


In [26]:
print("".join(["1", "2", "3"]))


123

Обратите внимание, что разделитель ставится только между строками, и никогда в конце.

Разделитель из нескольких символов:


In [27]:
shopping_list = ', '.join(['apples', 'milk', 'flour', 'jam'])
print(shopping_list)


apples, milk, flour, jam

Разделитель в виде перевода строки:


In [28]:
shopping_list = '\n'.join(['apples', 'milk', 'flour', 'jam'])
print(shopping_list)


apples
milk
flour
jam

Изменение символа строки

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

  • Преобразуют строку к списку и получают список символов (строк, состоящих из одного символа)
  • Изменяют один элемент списка
  • Список строк склеивают в одну большую строку

Пример:


In [29]:
a = "long string"  # у нас есть строка, мы хотим уметь ее изменять
print(a)

l = list(a)        # сделаем из строки список символов
print(l)

l[2] = "!"         # изменим один элемент списка
print(l)

s = "".join(l)
print(s)


long string
['l', 'o', 'n', 'g', ' ', 's', 't', 'r', 'i', 'n', 'g']
['l', 'o', '!', 'g', ' ', 's', 't', 'r', 'i', 'n', 'g']
lo!g string

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

Распаковка списков

Раньше мы уже встречались с такой конструкцией как параллельное присваивание:

a, b = c, d

Давайте ее немного обобщим. Если мы вместо двух значений c и d поставим один список, содержащий столько же элементов, сколько и переменных в левой части равенства, то Python проделает аналогичное параллельное присваивание.


In [30]:
a, b, c = [2, "abs", 3]  # Присваиваем в явном виде заданный список
print(a, b, c)


2 abs 3

In [31]:
lst = [2, "abs", 3]
a, b, c = lst  # Чуть менее тривиальная запись того же самого
print(a, b, c)


2 abs 3

Кроме того, можно распаковывать списки прямо в цикле for:


In [32]:
lst = [[1, 1], [2, 4], [3, 9], [4, 16]]

for a, b in lst:
    print(a, b)
print()

# То же самое в более привычной форме
for x in lst:
    a, b = x
    print(a, b)


1 1
2 4
3 9
4 16

1 1
2 4
3 9
4 16

Другие операции

Также для списков есть набор многих других удобных функций, уже встроенных в Python.

Минимум

Функция min ищет минимальный элемент списка:


In [33]:
l = [1, 2, -1, 3, 2, -2, 1, 5, 7, 3]
print(min(l))

# min можно брать и от двух элементов вместо списка
print(min(12, 10))


-2
10

Сумма

Функция sum считает сумму всех чисел списка:


In [34]:
print(sum([2, 3, 11, 1]))


17

Индекс элемента

Метод index находит индекс элемента в списке:


In [35]:
l = [1, 2, -1, 3, 2, -2, 1, 5, 7, 3]
print(l.index(3))  # В списке l у нас две тройки и index возвращает индекс первой из них


3

In [36]:
l = [1, 2, -1, 3, 2, -2, 1, 5, 7, 3]
print(l.index(115))  # Если элемента нет в списке, то произойдет ошибка выполнения


---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-36-84194bde2c42> in <module>()
      1 l = [1, 2, -1, 3, 2, -2, 1, 5, 7, 3]
----> 2 print(l.index(115))  # Если элемента нет в списке, то произойдет ошибка выполнения

ValueError: 115 is not in list

ValueError: 115 is not in list = ОшибкаЗначения: 115 не найдено в списке

Удаление элемента

Следующие методы изменяют именно текущий список, а не создают новый. Ни для одного из списков не поменяется id.

Метод pop удаляет и возращает последний элемент из списка:


In [37]:
l = [1, 2, 3]
last_element = l.pop()
print(l)
print(last_element)


[1, 2]
3

Вставка элемента

Метод insert(index, element) вставляет элемент element на место index, остальные элементы сдвигаются.


In [38]:
l = [1, 2, 4, 5]
l.insert(2, 3)
print(l)


[1, 2, 3, 4, 5]

Переворачивание списка

Метод reverse переворачивает список:


In [39]:
a = [1, 4, 2, 5, 2]
a.reverse()
print(a)


[2, 5, 2, 4, 1]