Python: List (Списки)
Список – это структура данных, которая содержит упорядоченный набор элементов, т.е. хранит последовательность элементов. Изменяемые списки создаются через квадратные скобки. Элементы могут повторяться и меняться. Доступ к отдельному элементу тоже через квадратные скобки. Отсчёт с 0.
Узнать все методы списка можно через команду.
help(list)
Рассмотрим некоторые примеры.
cats = ["Барсик", "Мурзик", "Васька"] print(cats) # все элементы списка print(cats[1]) # один указанный элемент numbers = [0, 1, 2, 3, 4, 5] print(numbers) print(numbers[4]) // список из строки mylist = list('Барсик') print(mylist)
В списке могут быть разные типы. Поместим в список числа и строки.
mix = ["one", 3, "two", "three", 9, 3] print(mix[1]) print(mix[2])
Можно создать пустой список.
empty = [] print(empty) # []
В качестве индекса можно указать отрицательные значения. Так индекс -1 вернёт последний элемент списка, -2 предпоследний и т.д.
numbers = [0, 1, 2, 3, 4, 5] print(numbers[-1]) #5 print(numbers[-2]) #4 print(numbers[-3]) #3
Развернуть список можно через reverse().
reversed = [1, 2, 3, 4, 4] reversed.reverse() print (reversed) # [4, 4, 3, 2, 1] kitten = list("Барсик") kitten.reverse() print(kitten) # ['к', 'и', 'с', 'р', 'а', 'Б']
Сортировать можно через sort().
mylist = [8, 2, 11, 4, 3] mylist.sort() print (mylist)
Можем заменить существующие элементы списка.
numbers = [0, 1, 2, 3, 4, 5] numbers[0] = 10 numbers[5] = 22 print(numbers[-1]) print(numbers[0])
Добавить новый элемент в конец списка можно через append().
numbers = [0, 1, 2, 3, 4, 5] numbers.append(99) print(numbers[-1])
Можно вставить элемент в нужную позицию через insert(), указав индекс.
numbers = [0, 1, 2, 3, 4, 5] numbers = [0, 1, 2, 3, 4, 5] numbers.insert(1, 33) print(numbers[1]) print(numbers) # [0, 33, 1, 2, 3, 4, 5]
Удалить элемент по указанному индексу можно через remove().
numbers = [0, 1, 2, 3, 4, 5] numbers.remove(5) print(numbers) # [0, 1, 2, 3, 4]
Метод pop() также позволяет удалить элемент по индексу, но при этом возвращает значение удалённого элемента. Если индекс не указан, то удаляется последний элемент.
numbers = [6, 3, 9, 5, 1, 5] poped = numbers.pop(2) print(poped) # 9 poped = numbers.pop() print(poped) # 5
Есть ещё способ удаления по индексу через инструкцию del.
Когда удаляется элемент с индексом 1, элемент, имевший индекс 2, становится элементом с индексом 1, элемент, имевший индекс 3, приобретает индекс 2 и так далее. Соответственно, количество индексов при удалении элемента уменьшается.
Можно запускать команду del numbers[1] снова и снова, удаляя по одному элементу списка. Главное, это вовремя остановиться, чтобы не получить ошибку при удалении несуществующего индекса.
Длину списка можно узнать через len().
numbers = [6, 8, 2, 5, 1, 5] print(len(numbers)) # 6
Узнать количество одинаковых элементов в списке можно через count().
kitten = list('котёнок') print(kitten.count('к')) # 2
Список можно расширить другим списком через extend(). Новые элементы добавляются в конец первого списка.
oneList = [6, 8, 2, 5, 1, 5] secondList = [0, 1, 4] oneList.extend(secondList) print(oneList) # [6, 8, 2, 5, 1, 5, 0, 1, 4]
Два списка можно сложить и получить третий список.
firstList = [6, 8, 2, 5, 1, 5] secondList = [0, 1, 4] bigList = firstList + secondList print(bigList) # [6, 8, 2, 5, 1, 5, 0, 1, 4]
Пройтись по всем элементам списка можно через цикл for.
numbers = [1, 2, 3] for element in numbers: print(element)
Фильтрация списка через filter() с лямбдой
Мы можем фильтровать элементы списка по заданному условию, используя класс filter и лямбда-выражения.
Допустим, у нас есть список чисел от 1 до 10 и мы хотим оставить числа меньше 5. Применяем к списку функцию filter(), в котором указываем лямбда-выражение — берётся каждый элемент списка и проверяется условие. Если число меньше 5, то условие выполняется и число попадает в объект класса filter. Затем мы создаём новый список, куда помещаем созданный объект и на выходе получаем финальный результат — отфильтрованный список.
sourceList = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] filterObj = filter(lambda x: x < 5, sourceList) print(type(filterObj)) # filteredList = list(filterObj) print(filteredList) # [1, 2, 3, 4]
Существует другой громоздкий вариант через цикл for, который не стал приводить здесь.
Вместо лямбда-выражения можно использовать именную функцию. Создадим именную функцию под именем isGreater и зададим условие - числа должны быть больше 5.
def isGreater(x): return x > 5 sourceList = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] filteredList = list(filter(isGreater, sourceList)) print(str(filteredList))
Проекция на список через map() с лямбдой
Если нужно пройтись по всем элементам списка и что-то с ним сделать, то подойдёт функция map(). Допустим, мы хотим увеличить значение каждого элемента на заданную величину.
sourceList = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] mapObj = map(lambda x: x + 9, sourceList) print(type(mapObj)) # mappedList = list(mapObj) print(mappedList) # [10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
Вырезка последовательности
Вырезка последовательности (получение фрагмента) применима к спискам, кортежам и строкам. Иногда используется термин "срез".
item[START:STOP:STEP]
Операция вырезки производится при помощи указания имени последовательности, за которым идёт пара чисел в квадратных скобках, разделённых двоеточием. Третий аргумент отвечает за шаг и используется реже (см. ниже).
Первое число перед двоеточием указывает позицию начала вырезки, а второе число после двоеточия указывает, где вырезка заканчивается. Если первое число не указано, вырезка начинается с начала последовательности. Если пропущено второе число, Python закончит вырезку у конца последовательности. Обратите внимание, что полученная вырезка будет начинаться с указанной начальной позиции, а заканчиваться прямо перед указанной конечной позицией, т.е. начальная позиция входит в вырезку, а конечная – нет.
sourceList = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] print(sourceList[1:4]) # со второго до четвёртого print(sourceList[5:]) # с шестого элемента до конца print(sourceList[1:-1]) # со второго до предпоследнего print(sourceList[:]) # все элементы
[2, 3, 4] [6, 7, 8, 9, 10] [2, 3, 4, 5, 6, 7, 8, 9] [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Можно указать шаг вырезки в третьем аргументе (по умолчанию шаг вырезки равен 1):
sourceList = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] print(sourceList[1:8:2]) # [2, 4, 6, 8]
с помощью срезов можно не только извлекать элементы, но и добавлять и удалять элементы (только для изменяемых списков).
sourceList = [1, 2, 3, 4, 5] sourceList[1:3] = [7, 7, 7] # добавим три новых элемента вместо второго и третьего элемента print(sourceList) # [1, 7, 7, 7, 4, 5] del sourceList[:-3] # удаляем первые элементы списка до третьего элемента с конца print(sourceList) # [7, 4, 5]
Д. П. Кириенко. Программирование на языке Python (школа 179 г. Москвы)
Часто в задачах приходится хранить прямоугольные таблицы с данными. Такие таблицы называются матрицами или двумерными массивами. В языке программирования Питон таблицу можно представить в виде списка строк, каждый элемент которого является в свою очередь списком, например, чисел. Например, создать числовую таблицу из двух строк и трех столбцов можно так:
A = [ [1, 2, 3], [4, 5, 6] ]
Здесь первая строка списка A[0] является списком из чисел [1, 2, 3] . То есть A[0][0] == 1 , значение A[0][1] == 2 , A[0][2] == 3 , A[1][0] == 4 , A[1][1] == 5 , A[1][2] == 6 .
Для обработки и вывода списка как правило используется два вложенных цикла. Первый цикл по номеру строки, второй цикл по элементам внутри строки. Например, вывести двумерный числовой список на экран построчно, разделяя числа пробелами внутри одной строки, можно так:
for i in range(len(A)): for j in range(len(A[i]): print(A[i][j], end = ' ') print()
То же самое, но циклы не по индексу, а по значениям списка:
for row in A: for elem in row: print(elem, end = ' ') print()
Естественно для вывода одной строки можно воспользоваться методом join :
for row in A: print(' '.join(list(map(str, row))))
Используем два вложенных цикла для подсчета суммы всех чисел в списке:
S = 0 for i in range(len(A)): for j in range(len(A[i])): S += A[i][j]
Или то же самое с циклом не по индексу, а по значениям строк:
S = 0 for row in A: for elem in row: S += elem
Списки
Список 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([])
Генератор списков
Зачастую требуется создать список, хранящий значения некоторой функции, например, квадратов чисел или арифметическую последовательность. Для этого можно воспользоваться синтаксическим сахаром 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 "", line 1, in 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 "", line 1, in 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
Сайт построен с использованием Pelican. За основу оформления взята тема от Smashing Magazine. Исходные тексты программ, приведённые на этом сайте, распространяются под лицензией GPLv3, все остальные материалы сайта распространяются под лицензией CC-BY.
Elem в питоне что это
Одна из самых мощных особенностей языка Python — расширенная запись списков, которая позволяет легко преобразовать один список в другой, применяя к каждому элементу функцию.
Пример 1.30. Введение в расширенную запись списков
>>> li = [1, 9, 8, 4] >>> [elem*2 for elem in li] [2, 18, 16, 8] >>> li [1, 9, 8, 4] >>> li = [elem*2 for elem in li] >>> li [2, 18, 16, 8]
| Чтобы понять такую запись, читайте ее справа налево. li — список, который вы преобразуете. Python пробегает по всем элементам li, временно присваивает каждый из них переменной elem, вычисляет значение выражения elem*2 и добавляет в конец списка, который вы в результате получаете. | |
| Обратите внимание, что при использовании расширенной записи списка исходный список не изменяется. | |
| Присваивание результата переменной, в которой хранится обрабатываемый список, безопасно, так как новый список создается в памяти и, когда вычисление выражения закончено, он присваивается переменной. |
Пример 1.31. Расширенная запись списка в buildConnectionString
["%s=%s" % (k, v) for k, v in params.items()]
Во-первых, обратите внимание на вызов метода items словаря params. Этот метод возвращает список кортежей, которые представляют записи в словаре.
Пример 1.32. keys, values, and items
>>> params = "server":"mpilgrim", "database":"master", "uid":"sa", "pwd":"secret"> >>> params.keys() ['server', 'uid', 'database', 'pwd'] >>> params.values() ['mpilgrim', 'sa', 'master', 'secret'] >>> params.items() [('server', 'mpilgrim'), ('uid', 'sa'), ('database', 'master'), ('pwd', 'secret')]
| Метод keys словаря возвращает список всех ключей. Порядок следования ключей в этом списке может не соответствовать порядку, в котором определялись записи словаря (помните, записи в словаре не упорядочены). | |
| Метод values возвращает список всех значений. Значения в этом списке идут в таком же порядке, как и ключи в списке, возвращаемом методом keys, то есть params.values()[n] == params[params.keys()[n]] для всех n. | |
| Метод items возвращает список всех записей словаря в виде кортежа (key, value). |
Давайте теперь посмотрим, что делает функция buildConnectionString. Она берет список params.items() и преобразует его, применяя к каждому элементу строку формата. Полученный список будет содержать такое же количество элементов, как и params.items(), но каждый элемент будет являться строкой с ключом и ассоциированным с ним значением из словаря params.
Пример 1.33. Расширенная запись списка в buildConnectionString, шаг за шагом
>>> params = "server":"mpilgrim", "database":"master", "uid":"sa", "pwd":"secret"> >>> params.items() [('server', 'mpilgrim'), ('uid', 'sa'), ('database', 'master'), ('pwd', 'secret')] >>> [k for k, v in params.items()] ['server', 'uid', 'database', 'pwd'] >>> [v for k, v in params.items()] ['mpilgrim', 'sa', 'master', 'secret'] >>> ["%s=%s" % (k, v) for k, v in params.items()] ['server=mpilgrim', 'uid=sa', 'database=master', 'pwd=secret']
| Обратите внимание, что мы используем две переменные при переборе элементов списка params.items(). Это — еще один пример использования множественного присваивания. Первым элементом списка params.items() является кортеж ('server', 'mpilgrim'), поэтому для первой итерации k получит значение 'server' и v получит значение 'mpilgrim'. В данном случае мы игнорируем v и включаем в результат только k, так что в результате мы получим список, эквивалентный params.keys(). | |
| Здесь мы делаем то же самое, но игнорируем k, так что в результате мы получим список, эквивалентный params.values(). | |
| Комбинируя эти два примера с простым форматированием, мы получаем список строк, содержащих ключ и значение для каждой записи словаря. Результат получается подозрительно похожим на вывод программы, все что осталось сделать — это объединить все элементы списка в одну строку. |
- Python Tutorial описывает другой способ преобразования элементов списка — с помощью всроенной функции map.
- Python Tutorial описывает, как использовать вложенные расширенные записи списков.
Copyright © 2000, 2001, 2002 Марк Пилгрим
Copyright © 2001, 2002 Перевод, Денис Откидач