pyth_03_list
Заметка 3. Список
курса Математический практикум по Питону.
Шокуров Антон В.
shokurov.anton.v@yandex.ru
http://машинноезрение.рф
Версия 0.19

Аннотация

Вводится базовый объект Питона (Python) список (list). Показано как его создавать, проверять принадлежность элемента, обращаться к одельным элементам (сложные индексы), и искать индекс элементов.

Ключевые слова: list, in, len, type и index.

Это предварительная версия! Любые замечания приветствуются.

Список -- основной объект питона!

Вычисления над отдельными числами это хорошо, но нам понадобиться список, например, чисел. Списки нужны хотябы для того, чтобы хранить наши данные (котировки акций, список товаров и тому подобное). Список позволяет хранить несколько значений, в общем случае, разных типов как если бы они были разными перемеными. Главное, что список подддерживает добавление новых элементов (в его конец), а также извлечение и удаление подсписков.

Создание

In [1]:
[4, 8, 15, 16, 23, 42] # Создаем список из 4 элементов.
Out[1]:
[4, 8, 15, 16, 23, 42]
In [2]:
# В момент создания список можно проинициализровать выражениями.
[ 2 + 5, 7 - 9] # Инициализировать, т.е. задать.
Out[2]:
[7, -2]
In [3]:
# Через явное преобразование. По аналогии с int, float, ...
list([11, 55, 10 - 13, -7, 8]) # list это объект.
Out[3]:
[11, 55, -3, -7, 8]

Чтобы были понятны принципы работы с ним, нужно его все-ткаи присвоить переменной.

In [4]:
# Присвоили переменной l список чисел.
l = [4, 8., 15, 16, 23, 42] # Внимание на второе число!
In [5]:
# Выведем его тип.
type( l ) # Видно, что он отличается от ранее используемых числовых типов.
Out[5]:
list
In [6]:
l # Выведем элементы списка.
Out[6]:
[4, 8.0, 15, 16, 23, 42]
In [7]:
# Оператор len позволяет узнать длину списка, т.е. количество элементов в нем.
len( l ) # Ранее встречался с str, строчкой.
Out[7]:
6

Проверка на принадлежность списку

Очевидно, важно иметь возможность проверки принадлежности элемента списку. Делается это так.

In [8]:
4 in l # Проверяем 4 принадлежит списку l.
Out[8]:
True
In [9]:
type( 4 in l ) # Возращается нам знакомый тип bool.
Out[9]:
bool
In [10]:
# Выполняются нужные преобразования типа.
4.0 in l, 8 in l, 8.0 in l # Речь о том, что в списк 8., т.е. float.
# А здесь 8, т.е. тип int.
Out[10]:
(True, True, True)
In [11]:
9 in l # Как легко видеть 9 не принадлежит списку.
Out[11]:
False
In [12]:
9 not in l # Можно проверить и отрицание.
Out[12]:
True
In [13]:
not 9 in l # Можно и так. Но правильнее not in.
Out[13]:
True
In [14]:
not 4 in l # для полноты картины.
Out[14]:
False

Пронумерованные переменные

Индекс

К списку можно относится как проиндексированныйм (пронумерованным) переменным.

In [15]:
l # Напомним содержимое списка.
Out[15]:
[4, 8.0, 15, 16, 23, 42]
In [16]:
# Число в квадратных скобках указывает на индекс в списке.
l[3] # Внимание, элементы списка нумеруются с 0.
Out[16]:
16
In [17]:
# Индекс должен соответствовать существующему элементу списка.
l[7] = 2 # Иначе будет ошибка. В списке нет такого индекса.
---------------------------------------------------------------------------
IndexError                                Traceback (most recent call last)
<ipython-input-17-dd9977053e6f> in <module>
      1 # Индекс должен соответствовать существующему элементу списка.
----> 2 l[7] = 2 # Иначе будет ошибка. В списке нет такого индекса.

IndexError: list assignment index out of range

Раз нумерация индекса начинается с нуля, а количество элементов 6, то последний валидный индекс равен 5.

In [18]:
l[6] # Это граничный элемент.
---------------------------------------------------------------------------
IndexError                                Traceback (most recent call last)
<ipython-input-18-866e352db5be> in <module>
----> 1 l[6] # Это граничный элемент.

IndexError: list index out of range
In [19]:
l[5] # Этот индекс уже валидный.
Out[19]:
42

Тип элементов списка

In [20]:
type( l[3] ) # Но, тип самого элемента списка ествественно свой, числовой.
Out[20]:
int
In [21]:
# Можно присловить другое значение элементу списка.
l[2] = 1 # Отсылка к прониндексированым переменным.
l # Выводим значение переменной l, т.е. списк чисел
Out[21]:
[4, 8.0, 1, 16, 23, 42]
In [22]:
# Тип у разных элементов списка может быть разным.
type( l[1] ), l[1] # float
Out[22]:
(float, 8.0)
In [23]:
type( l[3] ), l[3] # int
Out[23]:
(int, 16)

Сложный индекс

In [24]:
# Можно указывать диапазон индексов: от и до.
l[3:5] # Причем, "до" невключительно, т.е. в данном случае индексы: 3 и 4.
Out[24]:
[16, 23]
In [25]:
# При задании интервала индесов диапазон может выходить за пределы списка.
l[3:100] # В таком случае диапазон будет укорочен.
#  Ошибкой это считаться не будет.
Out[25]:
[16, 23, 42]
In [26]:
l[2:] # Если после двоеточия числа нет, то значит нужно идти до конца списка.
Out[26]:
[1, 16, 23, 42]
In [27]:
# Если числа нет до двоеточия,
l[:4] # то значит новый список начинется с начала данного.
Out[27]:
[4, 8.0, 1, 16]
In [28]:
# Явный вид указания последнего индекса,
l[2:len(l)] # который невключительный.
Out[28]:
[1, 16, 23, 42]
In [29]:
# Если чуть меньше,
l[2:len(l) - 1] # то не все элементы (промущен последний).
Out[29]:
[1, 16, 23]
In [30]:
# Если начало начинается после конца,
l[5:1] # то конечно получим "пустое множество", т.е. список.
Out[30]:
[]
In [31]:
# Даже если границы совпадают,
l[4:4] # всеравно пусто.
Out[31]:
[]
In [32]:
# Итого, если не указывать явно одну из границ диапазона индексов, то индексы беруться по масимому. 
l[:5], l[3:] # в даном случае, соответственно, с начала и до конца.
Out[32]:
([4, 8.0, 1, 16, 23], [16, 23, 42])

Шаг индекса

In [33]:
# В расширенном варианте можно указать шаг увеличения индекса. 
l[1:100:2] # Шаг указывается после второго двоеточия.
# В данном случае он равен 2, т.е. каждый второй.
Out[33]:
[8.0, 16, 42]
In [34]:
# Ествественно в расширенном варинте тоже можно опускать числа.
l[1::2] # Смысл будет прежним.
Out[34]:
[8.0, 16, 42]
In [35]:
# По умолчанию шаг равен 1,
l[3::1] # но можно явно это указать.
Out[35]:
[16, 23, 42]
In [36]:
l[3::]
Out[36]:
[16, 23, 42]

Упр. Как из списка извлечть два подсписка элементы которых поочередно содержать элементы из первоначального списка?

Отрицательные параметры индекса

Казалось бы что будет если взять отрицательный индекс? Мы же выйдем за границу...

In [37]:
# Отмечу, что элементы списка можно нумировать и с конца. 
l[-1] # Для этого используются отрицательные индексы.
# -1 соответствует первому элементу с конца, т.е. последнему.
Out[37]:
42
In [38]:
l[-2] # Предпоследний элемент или иначе второй элемент с конца.
Out[38]:
23
In [39]:
# Но всетаки всему есть предел...
l[-7] # и отрицательным индексам тоже.
---------------------------------------------------------------------------
IndexError                                Traceback (most recent call last)
<ipython-input-39-02f6401a696a> in <module>
      1 # Но всетаки всему есть предел...
----> 2 l[-7] # и отрицательным индексам тоже.

IndexError: list index out of range
In [40]:
# Такие элементы также можно использовать при задании диапазона индексов.
l[:-2] # В данном случае, извлекутся все элементу кроме двух посдних.
Out[40]:
[4, 8.0, 1, 16]

Отрицательный шаг

In [41]:
# Шаг тоже может быть отрицательный.
l[::-1] # В даном случае получится список в обратном порядке.
Out[41]:
[42, 23, 16, 1, 8.0, 4]
In [42]:
# Аналог начало идет после конца.
l[-1:2] # Поэтому пустой список.
Out[42]:
[]
In [43]:
# Но можно же шаг взять отрицательным.
l[-1:2:-1] # Тогда список будет обойден в обратную сторону: -1(5), -2(4), -3(3), -4 (2). В скобках реальный индекс.
Out[43]:
[42, 23, 16]
In [44]:
l[-1:-4:-1] # Но так будет понятнее.
Out[44]:
[42, 23, 16]
In [45]:
l[-2:3:-1] # Очередной пример для закрепления материала.
Out[45]:
[23]

Упр. Как переставить в обратном порядке элементы списка с четным индексом?

Присвоение сразу нескольким элементам списка

In [46]:
l[1:3] # Смотрим какие значения были до.
Out[46]:
[8.0, 1]
In [47]:
# Присвоить можно и диапазону значений сразу:
l[1:3] = 23, 7 # Список чисел должен соответствовать количеству (слева).
l
Out[47]:
[4, 23, 7, 16, 23, 42]
In [48]:
l[2:4] = [4, -7] # А можно и так.
l
Out[48]:
[4, 23, 4, -7, 23, 42]

Разнородные элементы

In [49]:
# В заключении обсуждения списков отмечу, что их элементы не обязаны иметь один и тот же тип
ll = [2, "строка текста", 6]
ll
Out[49]:
[2, 'строка текста', 6]
In [50]:
# Элемент с индексом 0 и 2 содержит
ll[0], ll[2]
Out[50]:
(2, 6)
In [51]:
type(ll[0]), type(ll[2]) # В тоже время.
Out[51]:
(int, int)
In [52]:
ll[1], type( ll[1] ) # А элемент с индексом 1 являтся строчкой.
Out[52]:
('строка текста', str)

Последнее показывает, что списки могут соедржать совершенно разнородные объекты. В этом смысле они полноценные.

In [53]:
# Поэтому, естественно, что списки могут содержать списки.
a = [ 2, 3, [4, 5], 8] # Список из трех элементов.
a
Out[53]:
[2, 3, [4, 5], 8]
In [54]:
# Нулевой, первый и третьий содержат числа:
a[0], a[1], a[3]
Out[54]:
(2, 3, 8)
In [55]:
# А вот второй элемент сам является списком:
a[2], type(a[2])
Out[55]:
([4, 5], list)
In [56]:
a[2][1] # Обращаемся ко второму элементу вложенного списка.
Out[56]:
5
In [57]:
a[2][0] = -5 # Можно и что-то присвоить.
a
Out[57]:
[2, 3, [-5, 5], 8]
In [58]:
[4, 5] in a # Можно конечно проверить принадлежность списку более сложных объектов.
Out[58]:
False
In [59]:
a[2]
Out[59]:
[-5, 5]

Рекурсия из списков

In [60]:
ll=[1,2,3] # Создаем список.
ll
Out[60]:
[1, 2, 3]
In [61]:
ll[1] = ll # Присваиваем его второму элементу.
In [62]:
# С интересом выводим.
ll # Ну хорошо, что система не повисла.
Out[62]:
[1, [...], 3]
In [63]:
ll[1] = "kkk" # От таких фокусов подальше присваиваем строчку.
In [64]:
ll
Out[64]:
[1, 'kkk', 3]

Поиск

In [65]:
l # Напомним элементы списока.
Out[65]:
[4, 23, 4, -7, 23, 42]
In [66]:
l.index(23) # Ищет индекс первого вхождения числа 23.
Out[66]:
1
In [67]:
l[1] # Проверим.
Out[67]:
23
In [68]:
l.index(23, 2) # Ищет первое вхождение числа 23 начиная со второго индекса.
Out[68]:
4
In [69]:
l[4] # Еще раз проверим.
Out[69]:
23
In [70]:
l.index(23, 2, 4) # Ищет первое вхождение начиная со второго индекса по пятый невключительно. Ошибка!
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-70-c496f55ecc87> in <module>
----> 1 l.index(23, 2, 4) # Ищет первое вхождение начиная со второго индекса по пятый невключительно. Ошибка!

ValueError: 23 is not in list
In [ ]: