Списки
Содержание
Что это?
Список в Python это:
упорядоченная изменяемая последовательность объектов произвольных типов
Список Python является гибким в использовании объектом. Как инструмент, программист может использовать списки, например, для создания элементов линейной алгебры: точек, векторов, матриц, тензоров. Или, например, для таблицы с некоторыми данными.
Создание списка
Список можно создать при помощи литералов. Литерал - это код, который используется для создания объекта "вручную". Например, некоторые литералы уже изученных ранее объектов:
int
:5
,-23
float
:5.
,5.0
,-10.81
,-1.081e1
str
:'ABCdef'
,"ABCdef"
В случае списка литералом являются квадратные скобки []
, внутри которых через запятую ,
перечисляются элементы списка:
>>> []
[]
>>> [0, 1, 2, 3, 4]
[0, 1, 2, 3, 4]
>>> ['sapere', 'aude']
['sapere', 'aude']
>>> ['Gravitational acceleration', 9.80665, 'm s^-2']
['Gravitational acceleration', 9.80665, 'm s^-2']
>>> type([])
<class 'list'>
Генератор списков
Зачастую требуется создать список, хранящий значения некоторой функции, например, квадратов чисел или арифметическую последовательность. Для этого можно воспользоваться синтаксическим сахаром Python - генератором списка:
>>> arithm = [ x for x in range(10) ]
>>> squares = [ x**2 for x in range(10) ]
>>> arithm
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> squares
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
Однако злоупотреблять генераторами не стоит - если заполнение происходит по сложным правилам, лучше избежать использования генератора в пользу читаемости кода.
Метод list.append
Метод списков list.append
(англ. добавить в конец), как следует из перевода, добавляет элемент в конец списка.
В примере ниже инициализируется пустой список fibs
, а затем заполняется элементами:
>>> fibs = []
>>> fibs.append(1)
>>> fibs
[1]
>>> fibs.append(1)
>>> fibs
[1, 1]
>>> fibs.append(2)
>>> fibs
[1, 1, 2]
>>> fibs.append(3)
>>> fibs
[1, 1, 2, 3]
Функция list
Аналогично функциям преобразования типов int()
, float()
, str()
существует функция list()
, создающая список из итерируемого объекта.
Её можно использовать, например, для создания списка символов из строки:
>>> list("sapere aude")
['s', 'a', 'p', 'e', 'r', 'e', ' ', 'a', 'u', 'd', 'e']
>>> list(range(10))
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
Элементы списка: доступ и изменение
Для доступа к элементам списка используется операция взятия элемента по индексу. Для этого рядом с литералом или переменной списка необходимо подписать индекс элемента в квадратных скобках:
>>> ['Gravitational acceleration', 9.80665, 'm s^-2'][0]
'Gravitational acceleration'
>>> ['Gravitational acceleration', 9.80665, 'm s^-2'][1]
9.80665
>>> ['Gravitational acceleration', 9.80665, 'm s^-2'][2]
'm s^-2'
>>> l = [10, 20, 30]
>>> l[0]
10
>>> l[1]
20
>>> l[2]
30
Нумерация элементов списка начинается с нуля.
При запросе элемента по несуществующему индексу, происходит ошибка IndexError:
>>> l
[10, 20, 30]
>>> l[3]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IndexError: list index out of range
Поэтому всегда нужно быть уверенным, что индексация не выходит за пределы длины списка.
Получить её можно, как и для строк, с помощью функции len()
:
>>> l
[10, 20, 30]
>>> len(l)
3
>>> l[len(l) - 1]
30
Последняя конструкция встречается нередко, поэтому в Python существует возможность взять элемент по отрицательному индексу:
>>> l
[10, 20, 30]
>>> l[-1]
30
>>> l[-2]
20
>>> l[-3]
10
>>> l[-4]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IndexError: list index out of range
Таким образом для индекса n ≥ 0, l[-n]
эвивалентно l[len(l) - n]
.
Изменение элементов
Изменение элементов осуществляется с помощью присваивания:
>>> l = [10, 20, 30]
>>> l
[10, 20, 30]
>>> l[0] = 0
>>> l
[0, 20, 30]
>>> l[2] = 55
>>> l
[0, 20, 55]
Доступ в цикле while
>>> l
[0, 20, 55]
>>> i = 0
>>> while i < len(l):
... print(i, l[i])
... i += 1
...
0 0
1 20
2 55
>>>
Доступ в цикле for
Наиболее универсальный способ это использование генератора range:
>>> l
[0, 20, 55]
>>> for i in range(len(l)):
... print(i, l[i])
...
0 0
1 20
2 55
Питонизмы
Конструкции с использованием
while
иfor
, изложенные выше, имеют аналоги практически во всех языках программирования. Они универсальны, стандартны, переносимы из языка в язык.Этот раздел относится только к особенностям языка Python.
Не злоупотребляйте питонизмами, наша цель - освоить алгоритмы и структуры данных, а не Python.
В языке Python цикл for
на самом деле является синтаксическим сахаром, поддерживающим концепцию итерируемого объекта.
Его обобщённый синтаксис выглядит примерно так:
for item in any_iterable:
# тело цикла
Здесь item
это выбранное программистом имя переменной итерирования, которая доступна в теле цикла.
В начале каждой итерации в эту переменную помещается значение из any_iterable
.
Под any_iterable
может стоять любой итерируемый объект.
Знакомые нам примеры итерируемых объектов:
range
- генератор арифметической последовательности,for
"просит" новые значения у генератора, пока те не закончатсяstr
- строковый тип, итерирование происходит по символамlist
- список, итерирование происходит по элементам
Таким образом, "pythonic way" пробега по списку может выглядеть так:
>>> l
[0, 20, 55]
>>> for elem in l:
... print(elem)
...
0
20
55
Отсюда видно, что программист в таком случае теряет удобный способ получить индекс элемента, если он ему нужен.
Под подобные мелкие задачи существует множество "питонизмов" - специфических для языка Python инструментов.
Один из примеров - enumerate
- позволяет программисту получить в цикле индекс итерации (!) и сам элемент.
При таком использовании номер итерации совпадает с индексом элемента:
>>> l
[0, 20, 55]
>>> for i, elem in enumerate(l):
... print(i, elem)
...
0 0
1 20
2 55
Код приведённый для enumerate
выше, аналогичен универсальным:
>>> l
[0, 20, 55]
>>> for i in range(len(l)):
... elem = l[i]
... print(i, elem)
...
0 0
1 20
2 55
>>> l
[0, 20, 55]
>>> i = 0
>>> while i < len(l):
... elem = l[i]
... print(i, elem)
... i += 1
...
0 0
1 20
2 55
Соединение и копирование списков
Списки можно соединять in place, т.е. перезаписывая, с помощью метода list.extend
:
>>> a
[0, 1, 2]
>>> b
[3, 4, 5]
>>> a.extend(b)
>>> a
[0, 1, 2, 3, 4, 5]
>>> b
[3, 4, 5]
Или соединять, создавая новый список из исходных:
>>> a
[0, 1, 2]
>>> b
[3, 4, 5]
>>> c = a + b
>>> c
[0, 1, 2, 3, 4, 5]
С копированием списков нужно быть осторожным. Python никогда не осуществляет копирование явно:
>>> a
[0, 1, 2]
>>> b = a
>>> b
[0, 1, 2]
>>> b[0] = 123
>>> a
[123, 1, 2]
>>> b
[123, 1, 2]
В строчке b = a
лишь создаётся ещё одна ссылка на объект [0, 1, 2]
, которая присваивается переменной b
.
В итоге a
и b
будут указывать на один и тот же объект.
Чтобы создать копию, необходимо поэлементно создать новый список из исходного.
Например, с помощью функции list()
:
>>> a = [0, 1, 2]
>>> b = list(a)
>>> a
[0, 1, 2]
>>> b
[0, 1, 2]
>>> b[0] = 123
>>> a
[0, 1, 2]
>>> b
[123, 1, 2]
Ремарка о строках
На самом деле, мы уже ранее сталкивались со списками в предудыщих работах, когда использовали str.split
:
>>> s = "ab cd ef1 2 301"
>>> s.split()
['ab', 'cd', 'ef1', '2', '301']
Т.е. str.split
, по умолчанию, разбивает строку по символам пустого пространства (пробел, табуляция) и создаёт список из получившихся "слов".
Загляните в help(str.split)
, чтобы узнать, как изменить такое поведение, и разбивать строку, например, по запятым, что является стандартом для представления таблиц в файлах csv
(comma separated values).
Методом, являющимся обратным к операции str.split
является str.join
.
Он "собирает" строку из списка строк:
>>> s
'ab cd ef1 2 301'
>>> l = s.split()
>>> l
['ab', 'cd', 'ef1', '2', '301']
>>> l[-1] = '430'
>>> l
['ab', 'cd', 'ef1', '2', '430']
>>> ','.join(l)
'ab,cd,ef1,2,430'
>>> ' -- '.join(l)
'ab -- cd -- ef1 -- 2 -- 430'
Контест №5
Участвовать в контесте. (Альтернативная ссылка)