Часто в программах требуется хранить различные списки данных, например, список городов, число выигранных очков в серии игр, или значения некоторой функции:
Москва Санкт-Петербург Самара Казань Тверь | 1200 200 500 210 0100 | 0.5 0.55 0.6 0.4 |
Все это можно представить в виде упорядоченного списка, который в Python задается с помощью оператора квадратных скобок:
[элемент1, элемент2, …, элементN]
Например, для хранения городов можно задать такой список:
lst = ["Москва", "Санкт-Петербург", "Тверь", "Казань"]
И он будет упорядоченный, то есть, каждому элементу здесь соответствует свой порядковый индекс, начиная с нулевого:
Здесь синей рамкой отмечен сам список, внутри которого располагаются элементы.
Если мы посмотрим тип объекта, на который ссылается переменая lst:
type(lst)
то увидим значение «list». Это как раз и есть тип списка.
То есть, через переменную lst мы можем работать со списком в целом, и первое, что нас здесь интересует: как обратиться к определенному элементу этого списка?
Для этого используется такой синтаксис:
список[индекс]
Например,
lst[0] lst[2]
Но, если мы укажем не существующий индекс:
lst[5]
то возникнет ошибка. Чтобы этого избежать нам надо знать значение последнего индекса. Для этого можно воспользоваться функцией
len(список)
которая возвращает число элементов в списке:
len(lst)
вернет значение 4. Но, так как индексы начинаются с нуля, то последний индекс будет равен:
lastIndex = len(lst) – 1
То есть, можно записать вот так:
lst[len(lst)-1]
но можно и проще, вот так:
lst[-1]
Этот пример показывает, что при отрицательных индексах, мы начинаем движение с конца списка и значение -1 дает самый последний элемент.
Далее, для перебора элементов списка в Python очень удобно использовать цикл for:
lst = ["Москва", "Санкт-Петербург", "Тверь", "Казань"] for city in lst: print(city)
Смотрите, как это легко и просто делается!
Конечно, мы можем распечатать весь контейнер целиком, просто записав:
print(lst)
Но здесь нет перебора всех элементов, а просто печать содержимого.
Вернемся к циклу. Здесь переменная city будет ссылаться на элементы внутри списка lst. Давайте выведем в консоль дополнительно еще тип выводимого значения:
print(city, type(city))
Увидим везде строковый тип str.
Но раз city ссылается на элементы списка, можно ли их изменить, присвоив этой переменной другое значение?
city = "новое значение"
Если мы теперь выведем список lst в консоль:
print(lst)
то окажется, что список не изменился. Почему?
Дело в том, что когда мы присваиваем переменной новое значение, то она просто начинает ссылаться на новый объект и на состоянии списка это никак не сказывается.
Вот этот момент работы переменных как ссылок на объекты всегда следует учитывать при программировании на Python. Также следует помнить, что в этом языке типы данных делятся на два класса: изменяемые и неизменяемые.
Все предыдущие типы, что мы проходили на прошлых занятиях относились к неизменяемым.
Это были:
числа, булевые значения, строки
Но вот список list относится к изменяемым типам, то есть, мы можем изменить его состояние, не создавая нового объекта.
В самом простом случае мы можем воспользоваться таким синтаксисом:
список[индекс] = значение
Например, так:
lst[0] = "Самара"
Теперь первый элемент не «Москва», а «Самара». В действительности, здесь произошло следующее:
Мы поменяли значение ссылки lst[0] первого элемента списка. Изначально она ссылалась на объект «Москва», а затем, стала ссылаться на объект «Самара». Прежний объект автоматически удаляется сборщиком мусора.
Вот так происходит изменение элементов списка, то есть, меняются значения ссылок на новые объекты.
Теперь вернемся к вопросу изменения элементов списка внутри цикла for. Предположим, у нас имеется список чисел:
digs = [-1, 0, 5, 3, 2]
и в цикле мы хотим его изменить на их квадраты.
Для этого запишем цикл в таком виде:
digs = [-1, 0, 5, 3, 2] for x in range(5): digs[x] **= 2 #digs[x] = digs[x]**2 print(digs)
Или, чтобы не указывать конкретное число в функции range, ее можно переписать так (вместо for x in range(5):)
for x in range(len(digs)):
И программа будет работать со списком произвольной длины.
Во всех наших примерах мы создавали списки небольшой длины и потому могли их запросто записать в программе.
Но что если требуется создать список размерностью в 100 или 1000 элементов? Для этого можно воспользоваться такой конструкцией, например:
A = [0]*1000
создает список из 1000 элементов со значением 0. Фактически, мы здесь сначала создали список из одного нулевого элемента, а затем, размножили его до тысячи. Или, можно сделать так:
A = ["none"]*100
Получим 100 элементов со строкой «none». И так далее. Кстати, если требуется создать пустой список, то это будет так:
A = []
Ну хорошо, есть у нас список из 100 или 1000 или другого числа элементов. Но как нам теперь с ним работать, например, занести туда какие-либо данные.
Для наглядности, предположим, пользователь вводит N чисел с клавиатуры (N<100) и пока он вводит положительные значения, мы их добавляем в список.
Как только он ввел какое-либо отрицательное число, считывание прекращается и мы вычисляем среднее арифметическое введенных значений.
Это можно реализовать так:
digs = [0]*100 N = 0; x = 0 while x >= 0: x = int(input("Введите целое число: ")) digs[N] = x N += 1 S = 0 for x in range(N): S += digs[x] S = S/N; print("S = %f, N = %d"%(S, N))
Теперь, когда мы в целом познакомились со списками, отметим следующие моменты.
Список может состоять из произвольных данных, например:
t = ["строка", 5, 5.7, True, [1,2,3]]
Причем, его длина
len(t)
будет равна 5, т.к. последний элемент – вложенный список здесь воспринимается как один отдельный элемент.
И этот пример показывает как можно создавать двумерные списки:
A = [[1,2,3], [4,5,6], [7,8,9]]
Для доступа к конкретному числу следует сначала обратиться к первому списку:
A[1]
а, затем, ко второму:
A[1][0]
Получим значение 4. С этими списками можно выполнять все те же самые операции, о которых мы говорили ранее, например, изменить значение:
A[1][2] = -1
Далее, списки можно объединять друг с другом, используя оператор +:
[1,2,3] + ["Москва", "Тверь"]
Используя этот оператор, можно добавлять новые элементы к списку:
digs = [1,2,3,4] digs = digs + [5] digs += [6]
или в начало:
digs = ["числа"]+digs
И здесь обратите внимание, что мы объединяем именно списки, то есть, вот такая запись:
digs = digs+3
приведет к ошибке, т.к. 3 – это число, а не список.
Следующий оператор:
3 in digs
возвращает True, если элемент, записанный слева, присутствует в списке, указанный справа. Иначе, значение False:
-1 in digs
Или, можно делать так:
[1,2,3] in A
То есть, в качестве элемента может быть любой тип данных.
Следующие две полезные функции:
digs = [1,2,3,4] max(digs) min(digs)
находят минимальное или максимальное числовое значение. И если в списке имеется не числовой элемент:
digs += "a"
то эти функции приводят к ошибкам.
Также можно вычислять сумму элементов числового списка:
d = [1,2,3,4] sum(d)
выполнять сортировку чисел по возрастанию:
d = [-1, 0, 5, 3, 2, 5] sorted(d)
или, по убыванию:
sorted(d, reverse=True)
Эта функция возвращает новый объект-список, прежний d остается без изменений.
Наконец, можно сравнивать списки между собой:
[1,2,3] == [1,2,3] [1,2,3] != [1,2,3] [1,2,3] > [1,2,3]
В последнем сравнении получим False, т.к. списки равны, но если записать так:
[10,2,3] > [1,2,3]
то первый список будет больше второго. Здесь сравнение больше, меньше выполняется по тому же принципу, что и у строк: перебираются последовательно элементы, и если текущий элемент первого списка больше соответствующего элемента второго списка, то первый список больше второго. И аналогично, при сравнении меньше:
[10,2,3] < [1,2,3]
Все эти сравнения работают с однотипными данными:
[1,2, "abc"] > [1,2, "abc"]
сработает корректно, а вот так:
[1,2,3] > [1,2, "abc"]
Произойдет ошибка, т.к. число 3 не может быть сравнено со строкой «abc».